SSM整合Shiro框架+Redis 实现权限管理

1.Shiro概述

Apache Shiro 是一个强大易用的 Java 安全框架

Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro 要简单的多。

简介

Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单;其基本功能点如下图所示:

SSM整合Shiro框架+Redis 实现权限管理_第1张图片

组件 描述
Authentication 身份认证 / 登录,验证用户是不是拥有相应的身份
Authorization 授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限
SessionManager

 

会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的。

 

 

Web环境中可使用DefaultWebSessionManager。

 

SecurityManager

 

安全管理器,即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互。

 

 

Web环境中可使用DefaultWebSecurityManager。

 

Realm 域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
Subject 主体,代表了当前 “用户”
SessionDAO 用于进行session序列化于反序列化的组件
CacheManager 用于进行缓存管理的组件
Cache 用于直接进行缓存操作的组件

2.自定义组件介绍

整合框架中自定义Shiro组件全部位于com.brillilab.ssmdemo.common.shiro包中

子包 描述
com.brillilab.ssmdemo.common.shiro.cache 自定义缓存组件,用于进行认证信息、权限信息和会话信息的缓存操作
com.brillilab.ssmdemo.common.shiro.filter 自定义权限过滤器
com.brillilab.ssmdemo.common.shiro.listenter 自定义会话监听器
com.brillilab.ssmdemo.common.shiro.realms 自定义Realms
com.brillilab.ssmdemo.common.shiro.session 自定义Session缓存管理组件,用于进行Sesssion缓存的操作,主要组件为SessionDAO和SessionRepository
com.brillilab.ssmdemo.common.shiro.token 自定义Token,使用不同的自定义Token可以实现不数据结构的Token
com.brillilab.ssmdemo.common.shiro.utils 相关工具包

3.配置文件

(1)applicationContext-shiro.xml的编写




    
    
        
        
        
    
    
    
        
        
        
        
    


    
    
        
        
        
        
    
      
    
        
    
    
    
        
    

    
    
        
        
        
        
        
        
    


    
    
    
        
        
    

    
    
        
        
        
        
        
        
        
            
                
            
        
        
        
        
        
        
        
        
        
    
    
    

    
    
        
    
    
    
        
        
        
        
        
        
    
    
    
        
    


    
    
        
    

    
    
        
        
        
        
        
        
            
                /common/** = anon
                /login = anon
                /index = anon
                /user/insert = login,permission
                /user/delete = login,permission
                /logout = anon
            
        
        
            
                
                
                
                
            
        
    
    
    
    
    
    
        
    

    
    

(2)web.xml的编写



    shiroFilter
    org.springframework.web.filter.DelegatingFilterProxy


    shiroFilter
    /*

*注意:shiro的自定义组件全部在com.brillilab.ssmdemo.shiro包中

4.Shiro基础操作的使用示例

以下所有操作均在web情景中进行

(1)登录校验

@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(User user, Boolean rememberme, HttpServletRequest request, HttpServletResponse response){
    try {
        //1.获取认证对象
        Subject subject = SecurityUtils.getSubject();


        //2.实例化Token对象
        String sessionId=request.getRequestedSessionId();
        String username=user.getUsername();
        String password=user.getPassword();

        UsernamePasswordToken token=new UsernamePasswordToken(username,password,rememberme);

        //3.进行登录认证
        subject.login(token);

    }catch (Exception e){
        return "error/loginerror";
    }

    return "redirect:/index";
}

(2)登出操作

@RequestMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response){

    Subject subject = SecurityUtils.getSubject();
    subject.logout();

    return "redirect:/index";
}

(3)自定义Realm

public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;
    @Autowired
    RoleService roleService;
    @Autowired
    PermissionService permissionService;

    /**
     * 授权信息,用于进行权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //(1)获得签名, 可做进一步查询
        User token= (User) principalCollection.getPrimaryPrincipal();
        User user=userService.login(token);
        //(2)创建SimpleAuthenticationInfo对象
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //(3)查询角色、权限信息
        Set roles = roleService.findRolesByUser(user);
        info.setRoles(roles);

        Set permissions = permissionService.findPermissionsByUser(user);
        info.addStringPermissions(permissions);
        return info;
    }

    /**
     *  认证信息,主要针对用户登录,
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //(1)获取登录的token
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
        //(2)获取username和password,调用登录
        String username=token.getUsername();
        String password=new String(token.getPassword());

        User user=new User();
        user.setUsername(username);
        user.setPassword(password);

        User login = userService.login(user);

        //(3)登录失败
        if (null==login){
            throw new AccountException("账号或密码不正确!");
        }
        if (login.getStatus()==0){
            throw new DisabledAccountException("帐号已经禁止登录!");
        }

        //(4)登录成功
        login.setUpdatetime(new Date());
        userService.updateUser(login);

        return new SimpleAuthenticationInfo(login,login.getPassword(),login.getUsername());
    }
}

(4)权限校验

    Subject subject = SecurityUtils.getSubject();

    List roles = Arrays.asList(new String[]{"admin", "super"});
    subject.hasAllRoles(roles); 
    subject.hasRole("admin");

(5)JSP页面内容授权

  • 在JSP页面引入Shiro标签ku

    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    
  • 标签中的类容在游客访问时显示

    
    
    
    
  • 标签中的内容在用户登录情况下,角色包含name属性值时显示

    
    
    
  • 标签中的类容在用户登录情况下,权限包含name属性值时显示

    
    
    

5.Shiro自定义权限过滤器

(1)自定义拦截器的配置



    
    
    
    
    
    
        
            /common/** = anon
            /login = anon
            /index = anon
            /user/insert = login,permission
            /user/delete = login,permission
        
    
    
        
            
            
        
    





(2)登录过滤器

1.LoginFilter

public class LoginFilter extends AccessControlFilter {
    /**
     * 写如何能通过该拦截器的逻辑
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
        //(1)获取认证信息
        User token = (User)SecurityUtils.getSubject().getPrincipal();
        //(2)登录请求直接放行
        if(null != token || isLoginRequest(request, response)){
            return true;
        }

        //(3)非登录请求,重定向到登录页面
        ResultVo result = ResultVoUtil.failed("当前用户没有登录!");
        WebUtil.jsonOut(response,result);

        return false;
    }

    /**
     * isAccessAllowed返回值为fales时经过该方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //保存Request和Response 到登录后的链接
        saveRequestAndRedirectToLogin(request, response);
        return false;
    }
}

(3)权限过滤器

2.RoleFilter

public class RoleFilter extends AccessControlFilter {
    /**
     * 写如何能通过该拦截器的逻辑
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object value) throws Exception {
        //(1)获取认证实体
        Subject subject = getSubject(request, response);
        //(2)进行角色校验(角色为"1"能通过)
        if (subject.hasAllRoles(Arrays.asList("1"))){
            return true;
        }
        //(3)未通过角色校验重定向回登录页面
        ((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
        return false;
    }

    /**
     * isAccessAllowed返回值为fales时经过该方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //(3)未通过角色校验重定向回登录页面
        //((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal()==null){
            //未登录重定向登录页面
            saveRequest(request);
            WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
        }else {
            //已登录重定向未授权错误页面
            WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/error/unauthorizerror");
        }
        return false;
    }
}

3.PermissionFilter

public class PermissionFilter extends AccessControlFilter {

    /**
     * 写如何能通过该拦截器的逻辑
     */    
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
        //(1)获取认证实体
        Subject subject = getSubject(request,response);
        //(2)进行权限校验
            //①获取请求url
        HttpServletRequest httpRequest=(HttpServletRequest)request;
        String url = httpRequest.getRequestURI();
        String contextPath = httpRequest.getContextPath();
        if (url!=null && url.startsWith(contextPath)){
            url = url.replaceFirst(contextPath,"");
        }
            //②权限校验
        if (subject.isPermitted(url)){
            return true;
        }
        return false;
    }

    /**
     * isAccessAllowed返回值为fales时经过该方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //(3)未通过权限校验的逻辑
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal()==null){
            //未登录重定向登录页面
            saveRequest(request);
            WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
        }else {
            //已登录重定向未授权错误页面
            WebUtil.jsonOut(response,ResultVoUtil.failed("用户未被授权该操作"));
        }
        return false;
    }
}

 

你可能感兴趣的:(框架学习)