美文网首页
Springboot项目引入shiro之用户登录校验(二)

Springboot项目引入shiro之用户登录校验(二)

作者: Bruce基 | 来源:发表于2020-04-27 14:41 被阅读0次

    说明

    上一章我们搭建好了springboot的基础框架,并引入了基础的orm框架和数据库等,今天主要集成shiro做登录权限的校验,废话不多说,开始构建程序代码。

    引入

    首先pom文件要引入shiro的jar包,如下:

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
    

    引入模板引擎freemarker:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
    
        <dependency>
            <groupId>net.mingsoft</groupId>
            <artifactId>shiro-freemarker-tags</artifactId>
            <version>0.1</version>
        </dependency>
    

    配置ShiroConfig

    package com.example.demo.config;
    
    import com.example.demo.core.shiro.MyShiroRealm;
    import com.example.demo.domain.properties.RedisProperties;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.codec.Base64;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.realm.Realm;
    import org.apache.shiro.session.mgt.SessionManager;
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.CookieRememberMeManager;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.servlet.SimpleCookie;
    import org.crazycake.shiro.RedisCacheManager;
    import org.crazycake.shiro.RedisManager;
    import org.crazycake.shiro.RedisSessionDAO;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.filter.DelegatingFilterProxy;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @author lu
     */
    @ConditionalOnWebApplication
    @Configuration
    @EnableConfigurationProperties({RedisProperties.class})
    public class ShiroConfig {
    
        @Bean
        public FilterRegistrationBean delegatingFilterProxy() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            DelegatingFilterProxy proxy = new DelegatingFilterProxy();
            proxy.setTargetFilterLifecycle(true);
            proxy.setTargetBeanName("shiroFilter");
            filterRegistrationBean.setFilter(proxy);
            return filterRegistrationBean;
        }
    
        @Bean("shiroFilter")
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setLoginUrl("/login/loginPage");
            shiroFilterFactoryBean.setSuccessUrl("/login/main");
            shiroFilterFactoryBean.setUnauthorizedUrl("/login/500");
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
            filterChainDefinitionMap.put("/login/**", "anon");
            filterChainDefinitionMap.put("/res/** ", "anon");
            filterChainDefinitionMap.put("/**", "authc");
            //错误页面,认证不通过跳转
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
    
        //    @Bean
    //    public Realm shiroRealm(HashedCredentialsMatcher matcher) {
    //        MyShiroRealm myShiroRealm = new MyShiroRealm();
    //        myShiroRealm.setCredentialsMatcher(matcher);
    //        return myShiroRealm;
    //    }
        @Bean
        public Realm shiroRealm() {
            return new MyShiroRealm();
        }
    
    
        @Bean
        public SecurityManager securityManager(RedisProperties commonProperties) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRememberMeManager(rememberMeManager());
            securityManager.setSessionManager(sessionManager(commonProperties));
            securityManager.setCacheManager(cacheManager(commonProperties));
            securityManager.setRealm(shiroRealm());
            return securityManager;
        }
    //    @Bean
    //    public SecurityManager securityManager(RedisProperties commonProperties) {
    //        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //        securityManager.setRememberMeManager(rememberMeManager());
    //        securityManager.setSessionManager(sessionManager(commonProperties));
    //        securityManager.setCacheManager(cacheManager(commonProperties));
    //        securityManager.setRealm(shiroRealm(hashedCredentialsMatcher()));
    //        return securityManager;
    //    }
    
        @Bean
        public SimpleCookie rememberCookie() {
            SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
            return simpleCookie;
        }
    
        @Bean
        public CookieRememberMeManager rememberMeManager() {
            CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
            cookieRememberMeManager.setCookie(rememberCookie());
            cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
            return cookieRememberMeManager;
        }
    
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("MD5");
            credentialsMatcher.setHashIterations(0);
            return credentialsMatcher;
        }
    
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        /**
         * 开启Shiro的注解支持
         * 比如:@RequireRoles @RequireUsers
         *
         * @param securityManager
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    
        @Bean
        public SessionManager sessionManager(RedisProperties commonProperties) {
            MySessionManager mySessionManager = new MySessionManager();
            mySessionManager.setSessionDAO(redisSessionDAO(commonProperties));
    //        mySessionManager.setCacheManager(cacheManager());
            mySessionManager.setSessionIdUrlRewritingEnabled(true);
            return mySessionManager;
        }
    
        @Bean
        public RedisManager redisManager(RedisProperties commonProperties) {
            RedisManager redisManager = new RedisManager();
            redisManager.setHost(commonProperties.getHost());
            redisManager.setPort(commonProperties.getPort());
            redisManager.setTimeout(commonProperties.getTimeout());
            redisManager.setPassword(commonProperties.getPassword());
            return redisManager;
        }
    
        /**
         * redis实现缓存
         *
         * @return
         */
        @Bean
        public RedisCacheManager cacheManager(RedisProperties commonProperties) {
            RedisCacheManager redisCacheManager = new RedisCacheManager();
            redisCacheManager.setRedisManager(redisManager(commonProperties));
            return redisCacheManager;
        }
    
        /**
         * 使用Redis实现 shiro sessionDao
         *
         * @return
         */
        @Bean
        public RedisSessionDAO redisSessionDAO(RedisProperties commonProperties) {
            RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
            redisSessionDAO.setRedisManager(redisManager(commonProperties));
            return redisSessionDAO;
        }
    
    
    }
    

    MySessionManager管理

    package com.example.demo.config;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.apache.shiro.web.util.WebUtils;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import java.io.Serializable;
    
    public class MySessionManager extends DefaultWebSessionManager {
    
        private static final String AUTHORIZATION = "X-Token";
        private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
    
        public MySessionManager() {
        }
    
        @Override
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
            //获取请求头中X-Token中保存的sessionId
            String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
            if (!StringUtils.isEmpty(id)) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
                return id;
            } else {
                //否则默认从cookie中获取sessionId
                return super.getSessionId(request, response);
            }
        }
    }
    

    reids缓存

    package com.example.demo.domain.properties;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "spring.redis")
    @Data
    public class RedisProperties {
        private String host;
        private int port;
        private String password;
        private int timeout;
        private int database;
    
    }
    

    你的ShiroRealm 处理

    package com.example.demo.core.shiro;
    
    import com.example.demo.domain.User;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    /**
     * shiroRealm 重写权限过滤
     *
     * @author lu
     */
    @Component
    public class MyShiroRealm extends AuthorizingRealm {
    
    
        /**
         * 登录信息和用户验证信息验证(non-Javadoc)
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
            String username = (String) token.getPrincipal(); // 得到用户名
            String password = new String((char[]) token.getCredentials()); // 得到密码
    
            if (null != username && null != password) {
                return new SimpleAuthenticationInfo(username, password, getName());
            } else {
                return null;
            }
    
        }
    
        /**
         * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法(non-Javadoc)
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
            User user = null;
            try {
                user = AuthUtil.getCurrentUser();
            } catch (Exception e) {
                e.printStackTrace();
            }
            SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
            simpleAuthorInfo.addStringPermissions(getPermCodes(user));
            return simpleAuthorInfo;
    
        }
    
        /**
         * 获取权限,string存放的是权限编码
         *
         * @param user
         * @return
         */
        private List<String> getPermCodes(User user) {
    
            //TODO 你的权限编码处理
            return null;
        }
    
    }
    

    用户session

    package com.example.demo.core.shiro;
    
    import com.example.demo.domain.User;
    import com.lulj.base.json.FastjsonUtils;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    
    /**
     * 用户公共类
     *
     * @author lu
     *
     */
    public class AuthUtil {
    
        /**
         * 获取当前用户
         *
         * @return
         */
        public static User getCurrentUser() throws Exception {
            User user;
            Subject sub = SecurityUtils.getSubject();
            Session session = sub.getSession();
            Object userJson = session.getAttribute("session_user");
            if (userJson != null) {
                user = FastjsonUtils.jsonToBean(User.class, userJson.toString());
            } else {
                return null;
            }
            return user;
        }
    
    }
    

    结束

    主要的部分是在shiroFilter进行过滤


    image.png

    MyShiroRealm做权限编码校验


    image.png

    说明

    版权声明:

    本文为博主原创文章,转载请附上原文出处链接和本声明。

    相关文章

      网友评论

          本文标题:Springboot项目引入shiro之用户登录校验(二)

          本文链接:https://www.haomeiwen.com/subject/zoakuhtx.html