Shiro Web集成

Shiro Web集成

推荐入门网站:http://how2j.cn/k/shiro/shiro-plan/1732.html    通俗易懂,主要是有Demo

                         https://www.w3cschool.cn/shiro/      较为详细,深入

难点:学习Shiro框架的最大难点,我觉得是一大批的陌生API,概念来袭,根本猝不及防,大的我是措手不及,连连败退,大战Shiro几天几夜后,算是入门了。

一:Shiro框架是一款权限管理的框架,主要功能为认证,授权,加密,会话管理。

Shiro的三大核心组件:

SecurityManager:你可以把它当成Struts2/SpringMVC的前端核心控制器,用于拦截请求并分发请求

Subject:Shiro的牌面,用于与外界交互

Realm:这个东西你可以把它作为一个验证器,或者数据源。用户信息封装为Token后传入Realm进行验证,并进行授权。

二:Shiro的流程

三:数据的配置

所需创建的表有5张,用户表(user),角色表(roles),权限表(permission),用户与角色之间的关系(user-roles),角色与权限之间的关系(roles-permission)

还需要创建查询的语句,mybatis,jbdc都行,这里用的是mybatis

public interface userDao {
	public String getPassword(Serializable name);

	public Set listRoles(Serializable name);

	public Set listPermissions(Serializable name);
	
	public void createUser(User user);
	
	public User getUser(Serializable name);
}

userDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.userDao">
	<select id="getPassword" resultType="String">
		select password from user where name=#{name}
	</select>
	<select id="listRoles" resultType="String">
	select r.name from user u
		left join user_role ur on u.id = ur.uid
		left join Role r on r.id = ur.rid
		where u.name = #{name}
	</select>
	<select id="listPermissions" resultType="String">
	select p.name from user u
		left join user_role ru on u.id = ru.uid
		left join role r on r.id = ru.rid
		left join role_permission rp on r.id = rp.rid
		left join permission p on p.id = rp.pid
		where u.name =#{name}
	</select>
	<insert id="createUser">
	insert into user values(null,#{name},#{password},#{salt})
	</insert>
	
	<select id="getUser" resultType="bean.User">
	select * from user where name=#{name}
	</select>
</mapper>

四:配置

web.xml

 <listener>
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
    </listener>
    <!-- 加载shiro.ini -->
    <context-param>
        <param-name>shiroEnvironmentClass</param-name>
        <param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
    <context-param>
        <param-name>shiroConfigLocations</param-name>
        <param-value>classpath:shiro.ini</param-value>
    </context-param>
    
    <!-- shiro过滤器 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

shiro.xml

[main] 
#使用数据库进行验证和授权
databaseRealm=shiro1.DatabaseRealm
securityManager.realms=$databaseRealm
 
#当访问需要验证的页面,但是又没有验证的情况下,跳转到login.jsp
authc.loginUrl=/login.jsp
#当访问需要角色的页面,但是又不拥有这个角色的情况下,跳转到noroles.jsp
roles.unauthorizedUrl=/noRoles.jsp
#当访问需要权限的页面,但是又不拥有这个权限的情况下,跳转到noperms.jsp
perms.unauthorizedUrl=/noPerms.jsp
 
#users,roles和perms都通过前面知识点的数据库配置了
[users] 
 
#urls用来指定哪些资源需要什么对应的授权才能使用
[urls] 
#doLogout地址就会进行退出行为
/doLogout=logout
#login.jsp,noroles.jsp,noperms.jsp 可以匿名访问
/login.jsp=anon
/noroles.jsp=anon
/noperms.jsp=anon
 
#查询所有产品,需要登录后才可以查看
/listProduct.jsp=authc 
#删除商品不仅需要登录,而且要拥有 productManager 权限才可以操作
/deleteProduct.jsp=authc,roles[productManager] 
#删除订单,不仅需要登录,而且要拥有 deleteOrder 权限才可以操作
/deleteOrder.jsp=authc,perms["deleteOrder"]  

原生Servlet

@WebServlet(name = "loginServlet", urlPatterns = "/login") 
public class LoginServlet extends HttpServlet { 
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException { 
        String name = req.getParameter("name"); 
        String password = req.getParameter("password"); 
        Subject subject = SecurityUtils.getSubject(); 
        UsernamePasswordToken token = new UsernamePasswordToken(name, password); 
        try { 
            subject.login(token);
            Session session=subject.getSession();
            session.setAttribute("subject", subject);
             
            resp.sendRedirect("");
        } catch (AuthenticationException e) { 
            req.setAttribute("error", "验证失败"); 
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        } 
    } 
} 

Realm

public class DatabaseRealm extends AuthorizingRealm {
 
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //能进入到这里,表示账号已经通过验证了
        String userName =(String) principalCollection.getPrimaryPrincipal();
        //通过DAO获取角色和权限
        Set<String> permissions = new DAO().listPermissions(userName);
        Set<String> roles = new DAO().listRoles(userName);
         
        //授权对象
        SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
        //把通过DAO获取到的角色和权限放进去
        s.setStringPermissions(permissions);
        s.setRoles(roles);
        return s;
    }
 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取账号密码
        UsernamePasswordToken t = (UsernamePasswordToken) token;
        String userName= token.getPrincipal().toString();
        String password= new String( t.getPassword());
        //获取数据库中的密码
        String passwordInDB = new DAO().getPassword(userName);
 
        //如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不是抛出具体错误原因
        if(null==passwordInDB || !passwordInDB.equals(password))
            throw new AuthenticationException();
         
        //认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealm
        SimpleAuthenticationInfo a = new SimpleAuthenticationInfo(userName,password,getName());
        return a;
    }

ok

猜你喜欢

转载自blog.csdn.net/qq_40008535/article/details/83108497
今日推荐