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);
//                    }
            }
        }

 

posted @ 2018-08-15 10:18  陽66  阅读(394)  评论(0编辑  收藏  举报