zoukankan      html  css  js  c++  java
  • shiro权限控制

    shiro权限控制

    1.权限控制

    1.1 什么是权限控制

    白话文:控制某某用户可以/不可以访问某某功能。

    我们今天的权限控制,实际上就是对资源加锁,每个锁都有一些规则,只有对应的钥匙才能打开,我们根据用户的角色,将钥匙分配给不同用户。

    1.2 权限控制的方式

    1、基于过滤器进行控制。比如我们servlet中的filter

    2、基于注解进行控制。可以借助spring的AOP进行控制。

    3、直接在业务代码中判断(不可取)

    4、页面标签的权限控制——不太常用。

    2.shiro简介

    2.1 功能

    认证:即我们常说的登录

    授权:给予用户资源权限

    会话:当前认证用户会话

    缓存:缓存认证权限等

     

    2.2 shiro核心流程

    图示

    ——这个图只要是用shiro必定逃离不了。

    2.3 权限控制方式:

    filter方式

    //设置过滤匹配路径和判断规则
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    filterChainDefinitionMap.put("/**", "anon");//可以匿名访问
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

    其中,shiro的filter列表,盗了一张图:

    过滤器别名对应的过滤器
    anon org.apache.shiro.web.filter.authc.AnonymousFilter
    authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
    authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
    logout org.apache.shiro.web.filter.authc.LogoutFilter
    noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
    perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
    port org.apache.shiro.web.filter.authz.PortFilter
    rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
    roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
    ssl org.apache.shiro.web.filter.authz.SslFilter
    user org.apache.shiro.web.filter.authc.UserFilter

    注解方式

    //在具体的方法上添加注解
    @RequiresAuthentication :表示当前Subject已经认证:Subject.isAuthenticated()返回true
    @RequiresUse:表示当前Subject已经身份验证或者通过记住我登录的
    @RequiresGuest :表示当前Subject没有身份验证或通过记住我登录过,即是游客身份
    @RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
    @RequiresPermissions(value={“user:select”, “user:all”}, logical= Logical.OR)

    只是用注解是不生效的,需要添加配置

    /**
    * 注解支持:
    */
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
       DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
       defaultAAP.setProxyTargetClass(true);
       return defaultAAP;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
       AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
       authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
       return authorizationAttributeSourceAdvisor;
    }

     

    标签(了解)

    注意,此处使用的是thymeleaf做视图界面展示,并非jsp
    <!--输出当前用户信息,通常为登录帐号信息。如果存入的principal是对象,可以通过property取值-->
    <span> <shiro:principal property="username"/> </span>

    <!--验证当前用户是否拥有指定权限。 -->
    <a shiro:hasPermission="user:select" href="#" >查看用户列表</a><!-- 拥有权限 -->

    <!--与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。-->
    <p shiro:lacksPermission="user:del"> 没有权限 </p>

    <!--验证当前用户是否拥有以下所有权限。-->
    <p shiro:hasAllPermissions="user:view, user:add">拥有所有才能访问</p>

    <!--验证当前用户是否拥有以下任意一个权限。-->
    <p shiro:hasAnyPermissions="user:view, user:del">拥有任意一个即可访问</p>


    <!--验证当前用户是否属于该角色。-->
    <a shiro:hasRole="role_admin" href="#">是role_admin角色</a>

    <!--与hasRole标签逻辑相反,当用户不属于该角色时验证通过。-->
    <p shiro:lacksRole="role_admin">我没有role_admin角色</p>

    <!--验证当前用户是否属于以下所有角色。-->
    <p shiro:hasAllRoles="developer, admin"> 角色与判断 </p>

    <!--验证当前用户是否属于以下任意一个角色。-->
    <p shiro:hasAnyRoles="admin, vip, developer"> 角色或判断 </p>

    <!--验证当前用户是否为“访客”,即未认证(包含未记住)的用户。-->
    <p shiro:guest="">访客 未认证</a></p>
       
    <!--已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。-->
    <p shiro:authenticated=""> <span shiro:principal=""></span> </p>  

    <!--未认证通过用户,与authenticated标签相对应。-->
    <!--与guest标签的区别是,该标签包含已记住用户。-->
    <p shiro:notAuthenticated=""> 未认证通过用户 </p>

     

    3.springboot整合shiro

    3.1 SecurityManager

    @Bean
    public SecurityManager securityManager(){
       DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
       List<Realm> realms = new ArrayList<Realm>();
       realms.add(customRealm());
       securityManager.setRealms(realms);
       securityManager.setSessionManager(sessionManager());
       return securityManager;
    }

     

    3.2 Realm

    //主要用作封装认证、授权信息,返回给安全管理器处理
    @Bean
    public CustomRealm customRealm(){
       CustomRealm customRealm = new CustomRealm();
       //设置密码校验算法——需要和加密算法一致
       customRealm.setCredentialsMatcher(credentialsMatcher());
       return customRealm;
    }

    @Bean
    public CredentialsMatcher credentialsMatcher(){
       HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
       hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
       //       hashedCredentialsMatcher.setHashIterations(2);
       return hashedCredentialsMatcher;
    }

     

    3.3 ShiroFilter

    @Bean
    public ShiroFilterFactoryBean shiroFilter2(SecurityManager securityManager){
       ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
       shiroFilterFactoryBean.setSecurityManager(securityManager);
       shiroFilterFactoryBean.setLoginUrl("/admin/toPage");
       Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
       //访问控制
       filterChainDefinitionMap.put("/admin/toPage", "anon");//可以匿名访问
       filterChainDefinitionMap.put("/admin/login", "anon");//可以匿名访问
       filterChainDefinitionMap.put("/storage/list", "perms[user:select]");//可以匿名访问
       //       filterChainDefinitionMap.put("/", "anon");//可以匿名访问
       filterChainDefinitionMap.put("/**", "anon");//可以匿名访问
       shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
       return shiroFilterFactoryBean;
    }

    3.4 SessionManager

    @Bean
    public SessionManager sessionManager() {
       DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
       sessionManager.setSessionDAO(redisSessionDAO());

       //设置会话过期时间
       sessionManager.setGlobalSessionTimeout(3*60*1000); //默认半小时
       sessionManager.setDeleteInvalidSessions(true); //默认自定调用SessionDAO的delete方法删除会话

       //设置会话定时检查
       sessionManager.setSessionValidationInterval(180000); //默认一小时
       sessionManager.setSessionValidationSchedulerEnabled(true);
       return sessionManager;
    }

    @Bean
    public SessionDAO redisSessionDAO(){
       ShiroSessionRedisDAO redisDAO = new ShiroSessionRedisDAO();
       return redisDAO;
    }

     

     

    3.4 用户新增

    在controller中接收新增用户后,交给service的saveAdmin做密码加密后保存

    public void saveAdmin(Administrator admin) {
       //对密码进行加密处理
       //1.得到明文密码
       String password = admin.getPassword();
       //2.生成随机盐 4-8位的随机数字
       String randomSalt = RandomStringUtils.randomNumeric(4, 8);
       admin.setPrivateSalt(randomSalt);
       //3.md5加密 添加随机盐,加密次数1次(当然,这个一次可以配置在配置文件在,此处注入读取)
       Md5Hash md5Hash = new Md5Hash(password,randomSalt,1);
       String hashPwd = md5Hash.toString();
       admin.setPassword(hashPwd);
       userMapper.insert(admin);
    }

     

    3.5 用户登录

    认证

    @Controller
    @RequestMapping("/admin")
    public class LoginController {

       @PostMapping("/login")
       public String login(
           @RequestParam("username") String username,
           @RequestParam("password") String password,Model map){
           try {
               Subject subject = SecurityUtils.getSubject();
               //处理登录的用户名密码token
               UsernamePasswordToken token =
                   new UsernamePasswordToken(username, password);
               //登录(开始认证)
               subject.login(token);
               return "redirect:/admin/main";
          }catch (UnknownAccountException ukactException){
               //用户不存在异常
               ukactException.printStackTrace();
               map.addAttribute("err_msg","用户不存在");
               return "login";
          }catch (IncorrectCredentialsException credentialExctption){
               credentialExctption.printStackTrace();
               map.addAttribute("err_msg","密码错误");
               return "login";
          }catch (Exception e){
               e.printStackTrace();
               map.addAttribute("err_msg","服务器错误,请重试");
               return "login";
          }
      }
    }

     

    3.6 用户访问(权限控制)

     

    4.其他

    4.1 thymeleaf中使用shiro标签的支持

    依赖坐标:

    <dependency>
       <groupId>com.github.theborakompanioni</groupId>
       <artifactId>thymeleaf-extras-shiro</artifactId>
       <version>2.0.0</version>
    </dependency>

    配置支持:

    @Bean
    public ShiroDialect shiroDialect(){
       return new ShiroDialect();
    }

     

    4.2 request判断ajax请求

    //通过头X-Requested-With=XMLHttpRequest来判断
    request.getHeader("X-Requested-With");

     

     

  • 相关阅读:
    条件语句实例
    数据类型
    C#与.NET概述
    c#循环
    语句
    数组

    英文文献中的数学符号
    如何计算协方差、 协方差矩阵 、 相关系数 、 马氏距离
    opengl 笔记
  • 原文地址:https://www.cnblogs.com/juddy/p/13568979.html
Copyright © 2011-2022 走看看