zoukankan      html  css  js  c++  java
  • springboot 学习之路 15(集成shiro)

    shiro:

      Apache Shiro 是 Java 的一个安全框架。功能强大,使用简单的Java安全框架,它为开发人员提供一个直观而全面的认证,授权,加密及会话管理的解决方案。

         更多shiro介绍参考:https://www.cnblogs.com/huhongy/p/8000049.html

    springboot与shiro整合:

      第一步:引入pom文件:

          

      第二步:自定义的UserRealm:

          

      第三步:登陆login:  

         

      第四步:shiro的配置文件:

         

       到这shiro基本整合完毕:后期我会完成配置一个完整的权限


    整合问题:  

      1:junit测试报错:UnavailableSecurityManagerException

        解决办法:缺少安全管理器,因为junit没注入进来,

        

        配置后在junit测试就可以了

      2:同一用户的单一登陆问题解决:在loginController加上:

        

        然后调用即可“

        

          第二种方式:过滤器实现:

        

    /**
     * 
     * @Title: KickoutSessionControlFilter.java
     * @Package com.agood.bejavagod.controller.filter
     * @Description: 同一用户后登陆踢出前面的用户
     */
    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;
        }
    
        public void setCacheManager(CacheManager cacheManager) {
            this.cache = cacheManager.getCache("shiro-kickout-session");
        }
    
        @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();
            ActiveUser user = (ActiveUser)subject.getPrincipal();
            String username = user.getUserName();
            Serializable sessionId = session.getId();
    
            // 同步控制
            Deque<Serializable> deque = cache.get(username);
            if(deque == null) {
                deque = new LinkedList<Serializable>();
                cache.put(username, deque);
            }
    
            //如果队列里没有此sessionId,且用户没有被踢出;放入队列
            if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
                deque.push(sessionId);
            }
    
            //如果队列里的sessionId数超出最大会话数,开始踢人
            while(deque.size() > maxSession) {
                Serializable kickoutSessionId = null;
                if(kickoutAfter) { //如果踢出后者
                    kickoutSessionId = deque.removeFirst();
                } else { //否则踢出前者
                    kickoutSessionId = deque.removeLast();
                }
                try {
                    Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
                    if(kickoutSession != null) {
                        //设置会话的kickout属性表示踢出了
                        kickoutSession.setAttribute("kickout", true);
                    }
                } catch (Exception e) {//ignore exception
                }
            }
    
            //如果被踢出了,直接退出,重定向到踢出后的地址
            if (session.getAttribute("kickout") != null) {
                //会话被踢出了
                try {
                    subject.logout();
                } catch (Exception e) { //ignore
                }
                saveRequest(request);
                
                HttpServletRequest httpRequest = WebUtils.toHttp(request);
                if (ShiroFilterUtils.isAjax(httpRequest)) {
                    HttpServletResponse httpServletResponse = WebUtils.toHttp(response);  
                    httpServletResponse.sendError(ShiroFilterUtils.HTTP_STATUS_SESSION_EXPIRE);
                    return false;
                } else {
                    WebUtils.issueRedirect(request, response, kickoutUrl);
                    return false;
                }
            }
    
            return true;
        }
    }

          第三种方式:  MemorySessionDAO  实现:

        

        

    Subject subject = SecurityUtils.getSubject();
            Collection<Session> sessions = sessionDao.getActiveSessions();
            if (subject.isAuthenticated()) {
                for (Session session : sessions) {
                    //方法一、当第二次登录时,给出提示“用户已登录”,停留在登录页面
                    if(username.equals(session.getAttribute("loginedUser"))){
                        subject.logout();
                        throw new RuntimeException("用户已登录");
                    }
                    //方法二、当第二次登录时,把第一个session剔除
    //                    if(username.equals(session.getAttribute("loginedUser"))){
    //                        session.setTimeout(0);
    //                    }
                }
            }
  • 相关阅读:
    475. Heaters
    69. Sqrt(x)
    83. Remove Duplicates from Sorted List Java solutions
    206. Reverse Linked List java solutions
    100. Same Tree Java Solutions
    1. Two Sum Java Solutions
    9. Palindrome Number Java Solutions
    112. Path Sum Java Solutin
    190. Reverse Bits Java Solutin
    202. Happy Number Java Solutin
  • 原文地址:https://www.cnblogs.com/huhongy/p/9479874.html
Copyright © 2011-2022 走看看