zoukankan      html  css  js  c++  java
  • Shiro (包含权限满足其中一个就通过的用法)

    方法/步骤

    1. web.xml添加配置


      <!-- shiro过滤器 -->

       <filter>

        <filter-name>shiroFilter</filter-name>

        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

        <init-param>

         <param-name>targetFilterLifecycle</param-name>

         <param-value>true</param-value>

        </init-param>

       </filter>

       <filter-mapping>

        <filter-name>shiroFilter</filter-name>

        <url-pattern>/*</url-pattern>

       </filter-mapping>

    2. shiro与spring整合配置


      <!-- 使用shiro安全检查注解 -->

       <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />

       <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

        <property name="securityManager" ref="securityManager" />

       </bean>



       <!-- shiro的生命周期处理器 -->

       <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

       <!-- shiro自带的密码匹配器(用来校验密码足够了) -->

        <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.SimpleCredentialsMatcher"></bean> 

       <!-- security datasource: -->

       <bean id="myRealm" class="cc.eguid.service.shiro.MyRealm">

        <property name="credentialsMatcher" ref="credentialsMatcher"/><!-- 密码匹配器 -->

              <property name="cachingEnabled" value="false"/><!-- 禁止缓存 -->

       </bean>

       <!-- 安全管理器 -->

       <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

        <property name="realm" ref="myRealm" />

       </bean>

       <!-- shiro过滤器 -->

       <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

        <!-- 配置安全管理器 -->

        <property name="securityManager" ref="securityManager" />

        <!-- 身份认证失败跳转的地址 -->

        <property name="loginUrl" value="/login/" />

        <!-- 身份认证成功跳转的地址 -->

        <property name="successUrl" value="/" />

        <!-- 权限认证失败跳转的地址 -->

        <property name="unauthorizedUrl" value="/login/unauthorized" />

        <property name="filterChainDefinitions">

         <!--anon 表示匿名访问,不需要认证以及授权 -->

         <!--authc表示需要认证 没有进行身份认证是不能进行访问的 -->

         <!--authc,roles[admin]表示是admin角色的用户才能访问 -->

         <value>

          /static/** = anon

          /login/** = anon

          /common/** = anon

          /admin/** = authc,roles[admin]

          /* = authc

          /** = authc

         </value>

        </property>

       </bean>

       

    3. realm和自定义密码校验器实现


      public class MyRealm extends AuthorizingRealm{

       Logger log=Logger.getLogger(MyRealm.class);

       @Autowired

          private UserService userService;//这是自己实现的用户信息操作类,实现用户信息,用户角色信息、用户权限信息查询功能

       @Override

       protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        UserInfo user = (UserInfo) principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        // 查询角色信息

        Collection<String> roles = userService.findRoles(user);

        info.addRoles(roles);

        log.info("shiro获取用户所属角色列表:"+roles);

        // 查询权限信息

        Collection<String> permissions = userService.findPermissions(user.getSystemuserid());

        info.addStringPermissions(permissions);

        log.info("shiro获取用户权限列表:"+permissions);

        return info;

       }

       @Override

       protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{

        //用户输入的用户名密码

        String loginname=  token.getPrincipal().toString();

        Object password=token.getCredentials();

        log.info("shiro正在处理尝试登录的用户信息:"+loginname+",密码:"+new String((char[])password));

        //数据库中的用户信息

        UserInfo user =userService.queryUserInfoByLoginName(loginname);

        if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){

         return null;

        }

        log.info("shiro获取到当前用户尝试登录的真实数据:"+user.getLoginusername()+",密码:"+user.getPassword());

        //数据库中的正确的账户信息

        AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName());

          

        //自己获取密码验证器(由于shiro实现的密码校验方法是密码错误会直接抛异常,不采用,所以改成直接手动校验)

        CredentialsMatcher matcher=getCredentialsMatcher();

        if(matcher==null){

         log.error("没有配置密码匹配器");

         return null;

        }

        //校验密码

        if(matcher.doCredentialsMatch(token,accountInfo)){

         return accountInfo;//校验通过,返回账号信息

        }

        

        return null;

       }

      }

    4. 自定义密码校验器


      /**

       * 自定义shiro密码匹配(密码是在md5散列值的基础上再次进行md5加盐操作,加盐值不保存在数据库,而是放在配置文件中)

       * @author eguid

       *

       */

      public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher {

       private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class);

       protected Object getCredentials(AuthenticationToken token) {

        return token.getCredentials();

       }

       protected Object getCredentials(AuthenticationInfo info) {

        return info.getCredentials();

       }

       @Autowired

       private CommonConfigs commonConfigs;

       /**

        * 验证密码

        *

        * @param tokenCredentials

        * @param accountCredentials

        * @return

        */

       protected boolean equals(Object tokenCredentials, Object accountCredentials) {

        if (log.isDebugEnabled()) {

         log.debug("Performing credentials equality check for tokenCredentials of type ["

           + tokenCredentials.getClass().getName() + " and accountCredentials of type ["

           + accountCredentials.getClass().getName() + "]");

        }

        if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {

         if (log.isDebugEnabled()) {

          log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing "

            + "array equals comparison");

         }

         byte[] tokenBytes = toBytes(tokenCredentials);

         byte[] accountBytes = toBytes(accountCredentials);

         return MessageDigest.isEqual(tokenBytes, accountBytes);

        } else {

         return accountCredentials.equals(tokenCredentials);

        }

       }

       public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        Object tokenCredentials = getCredentials(token);

        Object accountCredentials = getCredentials(info);

        String account=String.valueOf((char[])tokenCredentials);

        if(commonConfigs.getMd5salt()==null){

         if (log.isDebugEnabled()) {

          log.debug("配置文件中的加盐值为空,无法进行密码匹配,请确认配置文件是否在指定位置或配置指定加盐值");

         }

         return false;

        }

        String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt());

        if (log.isDebugEnabled()) {

         log.debug("加盐后的密码:"+saltaccount);

        }

        return equals(accountCredentials, saltaccount.toCharArray());

       }

      }

    5. 注解使用及模板标签使用

      1、注解使用
      @RequiresPermissions({"user:update:view"})//检查操作权限
      @RequiresPermissions(value={"user:add","user:view"},logical=Logical.OR)//两个操作权限其中一个满足条件即可通过检查
      @RequiresRoles({"admin"})//检查角色
      @RequiresRoles(value={"debug","admin"},logical=Logical.OR)//两个角色其中一个角色满足条件即可

      @RequiresAuthentication//检查是否通过shiro认证
      @RequiresGuest//不需要验证
      @RequiresUser//检查用户是否是当前系统中的用户

      2、标签使用
      使用标签需要先导入shiro的标签库<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
      (1)显示用户身份信息
      <shiro: principal/>
      默认调用Subject.getPrincipal()获取

      <shiro:principal property="username"/>
      相当于((User)Subject.getPrincipals()).getUsername()

      (2)已登录shiro用户显示

       <shiro:user> 
      欢迎[<shiro:principal/>]登录,<a href="logout">退出</a> 
      <shiro:user>

      (3)匿名用户访问
      <shiro:guest>未经过shiro验证的用户(游客,匿名用户)</shiro:guest> 

      (4)已经在shiro登录过的(已登录用户)

       <shiro:authenticated> 
          用户[<shiro:principal/>]已身份验证通过 
      <shiro:authenticated>

      (5)没有在shiro登录过的


       <shiro:notAuthenticated>
          未身份验证(包括记住我)
      <shiro:notAuthenticated>

      (6)检查角色

       <shiro:hasRole name="admin">
          用户[<shiro:principal/>]拥有角色admin<br/>
      <shiro:hasRole>

      检查任意角色(其中一个满足条件即通过,相当于OR)
       <shiro:hasAnyRoles name="admin,user">
          用户[<shiro:principal/>]拥有角色admin或user<br/>
      <shiro:hasAnyRoles>

      不具有角色(反向判断)
       <shiro:lacksRole name="abc">
          用户[<shiro:principal/>]不具有角色abc<br/>
      <shiro:lacksRole>

      (7)操作权限判断

       <shiro:hasPermission name="user:create"> 
          用户[<shiro:principal/>]拥有权限user:create<br/> 
      <shiro:hasPermission>   

      不具有操作权限(反向判断)


       <shiro:lacksPermission name="org:create"> 
          用户[<shiro:principal/>]没有权限org:create<br/> 
      <iro:lacksPermission> 

      END
  • 相关阅读:
    JAVA常见面试题之Forward和Redirect的区别
    [转载]vm文件
    [转载]vm文件
    [转载]心灵丨愿你早一点发现,你才是自己最重要的粉丝
    [转载]心灵丨愿你早一点发现,你才是自己最重要的粉丝
    iBatis整理——Spring环境下批处理实现
    iBatis整理——Spring环境下批处理实现
    SAP HANA 三大特点
    在解决方案中搜索 文件的位置
    我这边测了一下,发现#后面参数变化浏览器不会刷新,但是#一旦去掉就会刷新了,你那边的url拼的时候能不能在没参数的时候#也拼在里面,这样应该就OK了
  • 原文地址:https://www.cnblogs.com/LoveShare/p/11871697.html
Copyright © 2011-2022 走看看