• springboot结合shiro的配置类


    package com.jy.shiro.config;
    
    import com.jy.domain.admin.User;
    import com.jy.service.PermissionService;
    import com.jy.service.SysUserService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authc.credential.CredentialsMatcher;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.cache.CacheManager;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    import javax.annotation.Resource;
    import java.util.HashSet;
    import java.util.Set;
    
    public class MyShiroRealm extends AuthorizingRealm {
    
        @Resource
        private SysUserService sysUserService;
    
        @Resource
        private PermissionService permissionService;
    
        public MyShiroRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
            super(cacheManager, matcher);
        }
    
        public MyShiroRealm() {
        }
    
        /**
         * 认证信息.(身份验证) : Authentication 是用来验证用户身份
         * @param authcToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
            UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
            String username = (String) token.getPrincipal();
            User user = sysUserService.getUser(username);
    
            if (user == null) {
                /*没找到帐号*/
                throw new UnknownAccountException();
            }
            //帐号锁定
            if (Boolean.TRUE.equals(user.getLocked())) {
                throw new LockedAccountException();
            }
    
            //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    user.getUsername(),
                    user.getPassword(),ByteSource.Util.bytes(user.getSalt()),
                    getName()
            );
            return authenticationInfo;
        }
    
        /**
         * 授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            //获取的Principal是username是因为在认证的时候存放的信息就是user.getUsername();
            /*
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    user.getUsername(),
                    user.getPassword(),ByteSource.Util.bytes(user.getSalt()),
                    getName()
            );
             */
            String username = (String)SecurityUtils.getSubject().getPrincipal();
    
            SimpleAuthorizationInfo info =  new SimpleAuthorizationInfo();
            //设置角色
            Set<String> roleSet=new HashSet<String>();
            roleSet.add("admin");
            info.setRoles(roleSet);
            //设置对应的权限
            Set<String> permissionSet=permissionService.getUserPermission(username);
            info.setStringPermissions(permissionSet);
            return info;
        }
    
    
    
    }

     2.springboot  结合shiro的配置类

    package com.jy.shiro.config;
    
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    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.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @author 作者 z77z
     * @date 创建时间:2017年2月10日 下午1:16:38
     */
    @Configuration
    public class ShiroConfig {
    
        //配置自定义的密码比较器
        @Bean(name = "hashedCredentialsMatcher")
        public HashedCredentialsMatcher getHashedCredentialsMatcher() {
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("MD5");
            credentialsMatcher.setHashIterations(2);
            credentialsMatcher.setStoredCredentialsHexEncoded(true);
            return credentialsMatcher;
        }
    
        //配置自定义的权限登录器
        @Bean(name="authRealm")
        public MyShiroRealm authRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) {
            MyShiroRealm authRealm=new MyShiroRealm();
            authRealm.setCredentialsMatcher(matcher);
            return authRealm;
        }
    
        //配置核心安全事务管理器
        @Bean(name="securityManager")
        public DefaultWebSecurityManager securityManager(@Qualifier("authRealm") MyShiroRealm authRealm) {
            System.err.println("--------------shiro已经加载----------------");
            DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
            manager.setRealm(authRealm);
            return manager;
        }
    
        @Bean(name="shiroFilterFactoryBean")
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
    
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
            filterChainDefinitionMap.put("/favicon.ico", "anon");
            filterChainDefinitionMap.put("/assets/**", "anon");
            filterChainDefinitionMap.put("/logout", "anon");
            filterChainDefinitionMap.put("/login", "anon");
            filterChainDefinitionMap.put("/error", "anon");
            filterChainDefinitionMap.put("/**", "authc");
    
            shiroFilterFactoryBean.setLoginUrl("login");
            shiroFilterFactoryBean.setSuccessUrl("index");
            shiroFilterFactoryBean.setUnauthorizedUrl("error");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
        @Bean(name = "lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        @Bean
        @DependsOn("lifecycleBeanPostProcessor")
        public DefaultAdvisorAutoProxyCreator getAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
            creator.setProxyTargetClass(true);
            return creator;
        }
    
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
            creator.setProxyTargetClass(true);
            return creator;
        }
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
            AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(manager);
            return advisor;
        }
    
    }
    package com.jy.shiro.filter;
    
    
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
        protected Logger logger = LoggerFactory.getLogger(CustomFormAuthenticationFilter.class);
    
        @Override
        protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
    
            this.issueSuccessRedirect(request, response);
            return false;
        }
    
    }
    package com.jy.shiro.filter;
    
    
    import com.alibaba.fastjson.JSON;
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.DefaultSessionKey;
    import org.apache.shiro.session.mgt.SessionManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.filter.AccessControlFilter;
    import org.apache.shiro.web.util.WebUtils;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.Serializable;
    import java.util.Deque;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.Map;
    
    /**
     * 1.读取当前登录用户名,获取在缓存中的sessionId队列
     * 2.判断队列的长度,大于最大登录限制的时候,按踢出规则
     * 将之前的sessionId中的session域中存入kickout:true,并更新队列缓存
     * 3.判断当前登录的session域中的kickout如果为true,
     * 想将其做退出登录处理,然后再重定向到踢出登录提示页面
     */
    public class KickoutSessionControlFilter extends AccessControlFilter {
    
        private String kickoutUrl; //踢出后到的地址
        private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
        private int maxSession = 1; //同一个帐号最大会话数 默认1
    
        private SessionManager sessionManager;
        private Cache<String, Deque<Serializable>> cache;
    
        public void setKickoutUrl(String kickoutUrl) {
            this.kickoutUrl = kickoutUrl;
        }
    
        public void setKickoutAfter(boolean kickoutAfter) {
            this.kickoutAfter = kickoutAfter;
        }
    
        public void setMaxSession(int maxSession) {
            this.maxSession = maxSession;
        }
    
        public void setSessionManager(SessionManager sessionManager) {
            this.sessionManager = sessionManager;
        }
    
        //设置Cache的key的前缀
        public void setCacheManager(CacheManager cacheManager) {
            this.cache = cacheManager.getCache("shiro_redis_cache");
        }
    
        @Override
        protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
            return false;
        }
    
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            Subject subject = getSubject(request, response);
            if (!subject.isAuthenticated() && !subject.isRemembered()) {
                //如果没有登录,直接进行之后的流程
                return true;
            }
    
    
            Session session = subject.getSession();
            String username = (String) subject.getPrincipal();
            Serializable sessionId = session.getId();
    
            //读取缓存   没有就存入
            Deque<Serializable> deque = cache.get(username);
    
            //如果此用户没有session队列,也就是还没有登录过,缓存中没有
            //就new一个空队列,不然deque对象为空,会报空指针
            if (deque == null) {
                deque = new LinkedList<Serializable>();
            }
    
            //如果队列里没有此sessionId,且用户没有被踢出;放入队列
            if (!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
                //将sessionId存入队列
                deque.push(sessionId);
                //将用户的sessionId队列缓存
                cache.put(username, deque);
            }
    
            //如果队列里的sessionId数超出最大会话数,开始踢人
            while (deque.size() > maxSession) {
                Serializable kickoutSessionId = null;
                if (kickoutAfter) { //如果踢出后者
                    kickoutSessionId = deque.removeFirst();
                    //踢出后再更新下缓存队列
                    cache.put(username, deque);
                } else { //否则踢出前者
                    kickoutSessionId = deque.removeLast();
                    //踢出后再更新下缓存队列
                    cache.put(username, deque);
                }
    
    
                try {
                    //获取被踢出的sessionId的session对象
                    Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
                    if (kickoutSession != null) {
                        //设置会话的kickout属性表示踢出了
                        kickoutSession.setAttribute("kickout", true);
                    }
                } catch (Exception e) {//ignore exception
                }
            }
    
            //如果被踢出了,直接退出,重定向到踢出后的地址
            if ((Boolean) session.getAttribute("kickout") != null && (Boolean) session.getAttribute("kickout") == true) {
                //会话被踢出了
                try {
                    //退出登录
                    subject.logout();
                } catch (Exception e) { //ignore
                }
                saveRequest(request);
    
                Map<String, String> resultMap = new HashMap<String, String>();
                //判断是不是Ajax请求
                if ("XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request).getHeader("X-Requested-With"))) {
                    resultMap.put("user_status", "300");
                    resultMap.put("message", "您已经在其他地方登录,请重新登录!");
                    //输出json串
                    out(response, resultMap);
                } else {
                    //重定向
                    WebUtils.issueRedirect(request, response, kickoutUrl);
                }
                return false;
            }
            return true;
        }
    
        private void out(ServletResponse hresponse, Map<String, String> resultMap)
                throws IOException {
            try {
                hresponse.setCharacterEncoding("UTF-8");
                PrintWriter out = hresponse.getWriter();
                out.println(JSON.toJSONString(resultMap));
                out.flush();
                out.close();
            } catch (Exception e) {
                System.err.println("KickoutSessionFilter.class 输出JSON异常,可以忽略。");
            }
        }
    }
    人生没有彩排,每天都是现场直播!
  • 相关阅读:
    CSS处理小技巧
    React 脚手架构建
    Tomcat8学习
    javaScript(ES5中的类,原型,原型对象和函数对象的关系)
    保留两位小数(逢5进位,精度不会丢失)
    获取过去12个月
    mybatis 踩坑记录
    动态代理--jdk和cglib
    lambda表达式
    mybatis的mapper映射配置文件详解
  • 原文地址:https://www.cnblogs.com/northern-light/p/10498447.html
Copyright © 2020-2023  润新知