• shiro基本配置和使用


    这里讲shiro整合spring 实现登录验证 和权限拦截

    首先pom文件添加依赖

    <!-- shiro -->
    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-all</artifactId>
    <version>1.3.2</version>
    </dependency>

    <!-- spring整合shiro -->
    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
    </dependency>


    <!-- ehcache-->
    <dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>2.6.11</version>
    </dependency>

    shiro要结合ehcache这个缓存框架 可以实现一些功能 比如限制用户登录密码错误次数 然后限制多久时间内,限制登录

    接下来就来就是配置文件 首先web.xml
    <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
    <param-name>DelegatingFilterProxy</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>

    <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    这是配置一个shiro过滤器 将所有的请求都交给shiro处理 至于spring的配置我这里就不写了 和正常的配置一样

    然后ehcache缓存框架需要一个配置文件 我这里贴出来 文件名就叫 ehcache.xml
     1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  
     2 
     3        <diskStore path="${webapp.root}"/>  
     4      
     5     <defaultCache
     6             maxElementsInMemory="10000"
     7             maxElementsOnDisk="0"
     8             eternal="true"
     9             overflowToDisk="true"
    10             diskPersistent="false"
    11             timeToIdleSeconds="0"
    12             timeToLiveSeconds="0"
    13             diskSpoolBufferSizeMB="50"
    14             diskExpiryThreadIntervalSeconds="120"
    15             memoryStoreEvictionPolicy="LFU"
    16     />
    17    </ehcache>
    接下来就是spring整合shiro的配置文件
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     5 
     6 
     7 <!-- 配置ehCache缓存支持-->
     8 <bean name="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
     9 <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    10 </bean>
    11 
    12 
    13     <!-- 自定义Realm-->
    14 <bean name="userRealm" class="com.newer.web.shiro.MyRealm" >
    15 
    16     <!--注入加密算法类 -->
    17     <property name="credentialsMatcher">
    18 
    19     <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    20         <!--加密算法名 -->
    21         <property name="hashAlgorithmName" value="MD5"/>
    22         <!--加密次数 -->
    23         <property name="hashIterations" value="6"/>
    24     </bean>
    25 
    26     </property>
    27 
    28 
    29 </bean>
    30 
    31 
    32 <!-- shiro安全管理器-->
    33 <bean name="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    34 <property name="cacheManager" ref="cacheManager"></property>
    35 <property name="realm" ref="userRealm"></property>
    36 </bean>
    37 
    38 
    39 <!-- 管理shiro bean的生命周期 -->
    40 <bean name="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
    41 
    42 
    47 
    48     <!--shiro核心过滤器配置-->
    49     <bean name="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    50         <property name="securityManager" ref="securityManager"/>
    51         <property name="loginUrl" value="/login.jsp"></property> <!-- 没有认证  跳转的登录连接 -->
    52         <property name="unauthorizedUrl" value="/unauthorized.jsp"></property> <!-- 没有访问权限 跳转的页面 -->

    82 <!--这里使用 从数据库查询出来要拦截的url集合 注入到这个对象中 实现拦截 --> 83 <property name="filterChainDefinitionMap" ref="map"/> 86 </bean> 87 88 89 <!--实例工厂方法 将执行shiroFilterUtils类的build的方法 --> 90 <bean name="map" factory-bean="shiroFilterUtils" factory-method="build"/> 91 92 <!--这个类将从数据库中查询要拦截的url信息--> 93 <bean name="shiroFilterUtils" class="com.newer.util.ShiroFilterUtils"/> 97 </beans>

    别的配置不说  shiro核心过滤器bean的 name的值 一定要与web.xml里面配置的shiro过滤器的名字一样 否则会报错

    然后我这里是使用实例工厂方法  将一个存有要拦截的url的map集合 注入到ShiroFilterFactoryBean 中的filterChainDefinitionMap属性

    这样当我们的请求经过shiro过滤器时  会根据我们配置的要拦截的url和使用相应的拦截器 对请求进行处理  

    现在把我这个工具类贴出来

    /**
     * 这个类会在 spring容器初始化bean时  从数据库将要拦截的url
     * 查询出来 封装成集合  注入到ShiroFilterFactoryBean类的filterChainDefinitions属性中
     * 这样实现对需要相应权限才能访问的url进行拦截 并由shiro验证是否具有相应权限
     */
    
    public class ShiroFilterUtils {
    
      public Map<String,String> build(){
    
       
    
         Map<String,String> map= new LinkedHashMap<String, String>();

    //添加固定要拦截的url map.put("/user/login.do","anon"); map.put("/login.jsp","anon"); map.put("/**","authc"); return map; } }

    这里讲一下  url和拦截器的语法

    url使用的是 Ant风格

     ? 匹配任何单字符

     * 匹配0或者任意数量的字符

    ** 匹配0或者更多的目录

    拦截器常用有:
    anon 匿名的 不需要认证 也可以访问
    authc 必须认证才可以访问 没有认证会跳转登录链接
    user 登录之后启用了记住我功能 就可以访问

    roles 例如 roles[管理员] 表示必须具有管理员权限才可操作 如果是roles[管理员,经理] 表示要具有管理员和经理权限才可以访问
    ------------------------------------------
    shiro会将请求的url按照顺序和map集合中的所有url匹配 如果匹配到了 不会再匹配后续url 所以要注意 map集合中要拦截的url的顺序
    我这里就没有将要拦截的url 从数据库中查出 如果需要从数据集中查出 然后将要拦截的url作为key 要使用的拦截器作为value 存入这个map集合即可


    权限管理就这么多 接下来说登录认证 贴出我的controller
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/login")
        public String login(String userName, String userPassword, ModelMap map){
    
            //得到当前 Subject
            Subject currentSubject= SecurityUtils.getSubject();
    
                //创建用户名密码 token
                UsernamePasswordToken token= new UsernamePasswordToken(userName,userPassword);
    
                //记住当前用户 关掉浏览器 重开也能访问 不是authc 拦截器的url
                token.setRememberMe(true);
    
                try {
                    //执行登录方法
                currentSubject.login(token);
    
                }catch (IncorrectCredentialsException ie){
                    //将抛出的登录异常 存储 然后返回登录页面 显示给用户
                    map.put("loginMessage","用户名或密码错误!!!");
                    return "forward:/login.jsp";
    
                }catch (AuthenticationException ae){ //所有异常的父类
                  map.put("loginMessage","未知错误 请联系管理员");
                  return "forward:/login.jsp";
                }
    
    
            return "success";
        }
    
    
        @RequestMapping("/logout")
        public String logout(){
    
            //得到当前 Subject
            Subject currentSubject= SecurityUtils.getSubject();
    
            //注销当前 Subject
            currentSubject.logout();
    
          return "redirect:/login.jsp";
    
        }
    
    
    
    
    
    
       //这里面没有去写注册方法了  注册的时候 要将密码 通过这样加密后存入到数据库
        public static void main(String[] args) {
    
            //生成MD5加密的密码  参1:加密方式 ,参2:未加密的密码  参3:盐值 使用当前用户名  参4:加密次数
            Object str= new SimpleHash("MD5","123456","zhangsan",6);
    
            System.out.println("str = " + str);
        }
    
    
    }

    当执行
    login()方法时 会调用我们在shiro配置文件中配置的自定义Realm类 login方法出现错误 会抛出异常 我们用catch可以捕获对应异常

    接下来贴出我的
    Realm类
    @Component
    public class MyRealm extends AuthorizingRealm {
    
        @Autowired
        private UserService userService;
    
        @Autowired
        private AuthorityService authorityService;
    
    
    
        @Override    //认证方法
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    
            //将token强转成 用户密码token
            UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
    
            //根据传入的用户名 查询数据库  返回用户对象
            User user=userService.queryByUserName(token.getUsername());
    
            //没有查到用户 直接抛出异常
            if(user==null){
    
                throw  new IncorrectCredentialsException();
    
            }
    
            //根据当前用户名 生成盐值  用于结合加密算法对密码进行加密
            ByteSource salt=ByteSource.Util.bytes(token.getUsername());
    
            //将用户名和密码 交由shiro认证 如果出错会抛出对应异常   参数1:用户名 参数2:用户密码 参3:盐值 参数4:当前Realm的名字
            return new SimpleAuthenticationInfo(user.getUserName(),user.getUserPassword(),salt,this.getName());
    
        }
    
    
    
        @Override   //授权方法
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
            //获得用户名
            String userName= (String) principalCollection.getPrimaryPrincipal();
    
            //根据用户名 查询当前用户 拥有的权限
            Set<String>  roles=authorityService.queryByUserName(userName);
    
            //将当前权限集合 返回交给shiro处理 权限认证
            return new  SimpleAuthorizationInfo(roles);
        }
    
    
    
    
    
    }

    第二个授权方法  就是当请求需要对应权限的拦截器的url时   shiro会调用这个方法  然后我们根据当前用户名 查询出当前用户所拥有的权限

    然后交给shiro 由他去比对当前用户是否拥有可以访问的资格 如果没有就会跳转到我们在配置文件中 shiro过滤器配置的unauthorizedUrl属性的值去

    shiro的基本用法就这些  网上看了很多教程 都是各不相同  不像别的框架  教程都差不多  暂时总结到这里 后续有新的用法 再来加上吧 




    
    
  • 相关阅读:
    在FreeBSD中pkg包管理器使用实例
    租了一台华为云耀云服务器,却直接被封公网ip,而且是官方的bug导致!
    Java8 Stream对集合的一些应用
    idea 编码UTF-8 设置
    Java RSA非对称加密算法实现
    分库分表 策略 临时
    springboot+dubbo + zookeeper 案例
    跟着华为,学数字化转型(6):一把手工程
    跟着华为,学数字化转型(5):数据保护和业务决策
    跟着华为,学数字化转型(4):数据采集
  • 原文地址:https://www.cnblogs.com/java888/p/10958931.html
Copyright © 2020-2023  润新知