• Shiro集成web环境[Springboot]-认证与授权


    Shiro集成web环境[Springboot]--认证与授权

    在登录页面提交登陆数据后,发起请求也被ShiroFilter拦截,状态码为302

    <form action="${pageContext.request.contextPath}/user/login" method="post">
        Username:<input type="text" name="username"></br>
        Password:<input type="password" name="password"></br>
        <input type="submit" value="提交">
    </form>
    

    所以,必须将控制器的请求全部设置为匿名资源

    @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            Map<String,String> map = new HashMap<>();
            //多个过滤器  AnonymousFilter  匿名过滤器   anon
            // FormAuthenticationFilter 认证过滤器 authc
            map.put("/**","authc");
            map.put("/user/*","anon");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            shiroFilterFactoryBean.setLoginUrl("/main/login.jsp");
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public SecurityManager getSecurityManager(Realm realm){
            //web环境下securityManage的实现类为DefaultWebSecurityManager
            SecurityManager securityManager = new DefaultWebSecurityManager();
            ((DefaultWebSecurityManager) securityManager).setRealm(realm);
            return securityManager;
        }
    

    再次发起请求,ok 但由于认证未设置 所以没有成功的跳转。

    开发自定义Realm--认证与授权方法全部实现

    public class MyRealm extends AuthorizingRealm {
    
        @Autowired
        private UserMapper userMapper;
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
                throws AuthenticationException {
            String principal =(String) authenticationToken.getPrincipal();
            User user= new User();
            user.setUsername(principal);
            User user1 = userMapper.selectOne(user);
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal,user1.getPassword(),ByteSource.Util.bytes("salt"),this.getName());
            return authenticationInfo;
        }
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
            System.out.println("================================");
            User user= new User();
            user.setUsername(primaryPrincipal);
            User user1 = userMapper.selectOne(user);
            if(primaryPrincipal.equals(user1.getUsername())){
                SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
                authorizationInfo.addRole("super");
                authorizationInfo.addStringPermission("user:delete");
                authorizationInfo.addStringPermissions(Arrays.asList("admin:delete","admin:add"));
                return authorizationInfo;
            }
            return null;
        }
    }
    

    补充ShiroFilter,将SecurityManager,自定义Realm,CredentialsMatcher,CacheManager全部交由工厂管理:

    @Configuration
    public class ShiroFilterConf {
    
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //shiro会对所有资源进行控制,默认不拦截  需要配置
            Map<String,String> map = new HashMap<>();
            //多个过滤器  AnonymousFilter  匿名过滤器   anon
            // FormAuthenticationFilter 认证过滤器 authc
            map.put("/**","authc");
            map.put("/user/*","anon");
            map.put("/index.jsp","anon");
            //多个过滤器组成过滤器链
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            //设置认证页面路径
            shiroFilterFactoryBean.setLoginUrl("/main/login.jsp");
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public SecurityManager getSecurityManager(Realm realm,CacheManager cacheManager){
            //web环境下securityManage的实现类为DefaultWebSecurityManager
            SecurityManager securityManager = new DefaultWebSecurityManager();
            ((DefaultWebSecurityManager) securityManager).setRealm(realm);
            ((DefaultWebSecurityManager) securityManager).setCacheManager(cacheManager);
            return securityManager;
        }
    
        @Bean
        public Realm getRealm(CredentialsMatcher credentialsMatcher){
            MyRealm myRealm = new MyRealm();
            myRealm.setCredentialsMatcher(credentialsMatcher);
            return myRealm;
        }
    
        @Bean
        public CredentialsMatcher getCredentialsMatcher(){
            HashedCredentialsMatcher hm = new HashedCredentialsMatcher();
            hm.setHashAlgorithmName("MD5");
            hm.setHashIterations(1024);
            return hm;
        }
    
        @Bean
        public CacheManager getCacheManager(){
            CacheManager cacheManager = new EhCacheManager();
            return cacheManager;
        }
    }
    

    测试index页面

    <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %>
    <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
    <shiro:authenticated>
        hello:<shiro:principal></shiro:principal>&nbsp;&nbsp;<a href="${pageContext.request.contextPath}/user/logout">登出</a>
        <ul>
            <li>专辑</li>
            <li>章节</li>
            <li>用户</li>
            <shiro:hasRole name="super">
                <li>管理员</li>
                <shiro:hasPermission name="admin:delete">
                    删
                </shiro:hasPermission>
                <shiro:hasPermission name="admin:add">
                    增
                </shiro:hasPermission>
                <shiro:hasPermission name="admin:update">
                    改
                </shiro:hasPermission>
            </shiro:hasRole>
        </ul>
    </shiro:authenticated>
    
    <shiro:notAuthenticated>
        <a href="${pageContext.request.contextPath}/main/login.jsp">你好请登录</a>
    </shiro:notAuthenticated>
    </body>
    </html>
    

    shiro中相关的标签

    <shiro:principal></shiro:principal>  //用户的身份信息
    <shiro:authenticated></shiro:authenticated> //认证成功  执行标签体的内容
    <shiro:notAuthenticated></shiro:notAuthenticated> //未认证  执行标签体内容
    //基于角色的权限管理
    <shiro:hasRole name="super"></shiro:hasRole>
    <shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles>
    //基于资源的权限管理
    <shiro:hasPermission name="user:delete"></shiro:hasPermission>
    

    缓存问题

    如果没有缓存,一个Permission或者role判断要查询三次数据库-username查主体--主体查角色---角色查权限,这样对于数据库的压力太大,需要设置缓存。而且要注意到,在第一次查询时shiro就会多个Permission或者Role判断设置一次缓存,就是说,授权方法doGetAuthorizationInfo只走一次。
    shiro缓存是在内存中的。

    ehcache主包必须导入,shiro集成时CacheManager是没有实现的,主包中才有实现类EhCacheManager

    	@Bean
        public CacheManager getCacheManager(){
            CacheManager cacheManager = new EhCacheManager();
            return cacheManager;
        }
    
  • 相关阅读:
    JAVA Oauth 认证服务器的搭建
    ibatis 中isNull, isNotNull与isEmpty, isNotEmpty区别
    Java OAuth开发包资料
    hOAuth2.0认证和授权原理
    Spring+Quartz实现定时任务的配置方法
    cron表达式详解(Spring定时任务配置时间间隔)
    spring定时任务的配置使用
    [spring-framework]Spring定时器的配置和使用
    net.sf.json在处理json对象转换为普通java实体对象时的问题和解决方案
    大数据和拉普拉斯妖
  • 原文地址:https://www.cnblogs.com/mzc1997/p/10225647.html
Copyright © 2020-2023  润新知