zoukankan      html  css  js  c++  java
  • springboot 整合 shrio 和 token 记录

      1. shrio 整合中用到的几个 概念  

          1.1  realm 一般就是权限验证   很好理解 一般继承 AuthorizingRealm 类 实现自己的登录逻辑

          1.2 SessionManager 会话管理器 主要功能 管理创建session   sessionFactory   管理session 的缓存   cacheManager  

        1.3 SecurityManager 安全管理器  一般注入 自己的realm实现   自己的sessionManager实现

        1.4 ShiroFilterFactoryBean 过滤器 主要匹配 URL 和 shrio 过滤器
    2.具体实现 自定义realm
      
    package com.xhc.framework.config.shiro.realm;
    
    
    import com.xhc.common.utils.RandomUtil;
    import com.xhc.system.entity.SysUsers;
    import org.apache.shiro.SecurityUtils;
    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.authc.UsernamePasswordToken;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 自定义Realm 处理登录 权限
     * 
     * @author ruoyi
     */
    public class UserRealm extends AuthorizingRealm
    {
        private static final Logger log = LoggerFactory.getLogger(UserRealm.class);
    
    
        /**
         * 授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
        {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addRole("admin");
            info.addStringPermission("*:*:*");
            return info;
        }
    
        /**
         * 登录认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
        {
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
            String username = upToken.getUsername();
            final char[] password1 = upToken.getPassword();
            String password = "";
            SysUsers user=new SysUsers();
            user.setLoginAccount(username);
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password1, getName());
            return info;
        }
    
        /**
         * 清理缓存权限
         */
        public void clearCachedAuthorizationInfo()
        {
            this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
        }
    }
    

      

    注入自定义realm
    @Bean
        public SecurityManager securityManager(UserRealm userRealm)
        {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 设置realm.
            securityManager.setRealm(userRealm);
            
            return securityManager;
        }
    

      3.自定义sessionFactory会话 创建session

    package com.xhc.framework.config.shiro.session;
    
    import javax.servlet.http.HttpServletRequest;
    
    import com.xhc.common.utils.IpUtils;
    import com.xhc.common.utils.RandomUtil;
    import com.xhc.common.utils.ServletUtils;
    import eu.bitwalker.useragentutils.UserAgent;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.SessionContext;
    import org.apache.shiro.session.mgt.SessionFactory;
    import org.apache.shiro.session.mgt.SimpleSession;
    import org.apache.shiro.web.session.mgt.WebSessionContext;
    import org.springframework.stereotype.Component;
    
    
    /**
     * 自定义sessionFactory会话
     * 
     * @author ruoyi
     */
    @Component
    public class OnlineSessionFactory implements SessionFactory
    {
        @Override
        public Session createSession(SessionContext initData)
        {
    
    
    
            if (initData != null) {
                String host = initData.getHost();
                if (host != null) {
                    OnlineSession  session = new OnlineSession(); //自己继承的session 类 扩招功能
                    session.setHost(host);
                    System.out.println("创建sessionid"+session.toString());
                    return session;
                }
            }
            System.out.println("创建sessionid initData=null");
            return new OnlineSession();
    
        }
    }
    

      注入自己 实现

      @Bean
        public SessionManager sessionManager(){
            ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
            
            // 自定义sessionFactory
            shiroSessionManager.setSessionFactory(sessionFactory());
            
            return shiroSessionManager;
        }
    

      4.自定义缓存的实现   继承 EnterpriseCacheSessionDAO

    package com.xhc.framework.config.shiro.session;
    
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
    
    import java.io.Serializable;
    
    /**
     * 针对自定义的ShiroSession的db操作
     * 
     * @author ruoyi
     */
    public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
    {
        @Override
        protected Serializable doCreate(Session session) {
            System.out.println("doCreate"+session.toString());
            return super.doCreate(session);
        }
    
        @Override
        protected Session doReadSession(Serializable sessionId) {
            System.out.println("doReadSession sessionId"+sessionId);
            return super.doReadSession(sessionId);
        }
    
        @Override
        protected void doUpdate(Session session) {
            System.out.println("doUpdate"+session.toString());
            super.doUpdate(session);
        }
    
        @Override
        protected void doDelete(Session session) {
            System.out.println("doDelete"+session.toString());
            super.doDelete(session);
        }
    }

    注入配置中

     @Bean
        public SessionManager sessionManager(){
            ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
            //这里可以不设置。Shiro有默认的session管理。如果缓存为Redis则需改用Redis的管理
           shiroSessionManager.setSessionDAO(sessionDAO());
         
            return shiroSessionManager;
        }
    

      

    5.配置 shiro 过滤器 (url和过滤器匹配 自定义过滤器)

    @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
        {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            // Shiro的核心安全接口,这个属性是必须的
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            // 身份认证失败,则跳转到登录页面的配置
            shiroFilterFactoryBean.setLoginUrl(loginUrl);
            // 权限认证失败,则跳转到指定页面
            shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
            // Shiro连接约束配置,即过滤链的定义
            LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
            // 对静态资源设置匿名访问
    
            filterChainDefinitionMap.put("/favicon.ico", "anon");
            filterChainDefinitionMap.put("/static/**", "anon");
            filterChainDefinitionMap.put("/templates/**", "anon");
            // 退出 logout地址,shiro去清除session
            filterChainDefinitionMap.put("/system/loginOut", "anon");
            // 不需要拦截的访问
            filterChainDefinitionMap.put("/system/login", "anon");
            // 系统权限列表
            // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
    
    
            Map<String, Filter> filters = new LinkedHashMap<String, Filter>();

          //这里是自己实现的过滤器 注入的配置汇中 filters.put(
    "kickout", kickoutSessionFilter()); // 注销成功,则跳转到指定页面 shiroFilterFactoryBean.setFilters(filters); // 所有请求需要认证 filterChainDefinitionMap.put("/**", "kickout"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }
    anon 默认的不需要登录的过滤器
    filters.put("kickout", kickoutSessionFilter()); 是自己实现的过滤器
    先注入过滤器实现 再去匹配
    filterChainDefinitionMap.put("/**", "kickout");

    自定义过滤器
    package com.xhc.framework.config.shiro;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.xhc.common.vo.AjaxResult;
    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 javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * 登录帐号控制过滤器
     * 可以发现他是调用的isAccessAllowed方法和onAccessDenied方法,只要两者有一个可以就可以了,从名字中我们也可以理解,他的逻辑是这样:先调用isAccessAllowed,如果返回的是true,
     * 则直接放行执行后面的filter和servlet,如果返回的是false,则继续执行后面的onAccessDenied方法,如果后面返回的是true则也可以有权限继续执行后面的filter和servelt。
     * 只有两个函数都返回false才会阻止后面的filter和servlet的执行
     *
     * @author ruoyi
     */
    public class KickoutSessionFilter extends AccessControlFilter {
        @Override
        protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) {
            return false;
        }
    
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
    
            HttpServletRequest httpRequest = WebUtils.toHttp(request);
            HttpServletResponse httpResponse = WebUtils.toHttp(response);
             String requestURI = httpRequest.getRequestURI();
             String requestURL = httpRequest.getRequestURL().toString();
            Subject subject = getSubject(request, response);
            System.out.println("sessionid:"+subject.getSession().getId());
            System.out.println("requestURI:"+requestURI);
            System.out.println("requestURL:"+requestURL);
    
           //已结登录 或者 记住密码
            if (!subject.isAuthenticated() && !subject.isRemembered()) {
                // 如果没有登录或用户最大会话数为-1,直接进行之后的流程
                httpResponse.setContentType("application/json");
                httpResponse.setCharacterEncoding("utf-8");
                httpResponse.getWriter().print( new ObjectMapper().writeValueAsString(new AjaxResult().noPermission()));
                return false;
            }
            // 当前登录用户
            return true;
        }
    
    
    }

     6.如果想用token 更换cookie 的 验证 实现获取sessionid的逻辑 从 request 或者 head 头中获取 token

      

    package com.xhc.framework.config.shiro;
    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 ShiroSessionManager extends DefaultWebSessionManager {
    
        private static final String AUTHORIZATION = "token";
        @Override
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
    
            String id = WebUtils.toHttp(request).getParameter(AUTHORIZATION);
          //  String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
            System.out.println("getSessionId "+id);
    
            if (id!=null&&!id.equals("")) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.URL_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);
    
               request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
                return id;
            }
        }
    
    }

    注入配置中

     @Bean
        public SessionManager sessionManager(){
            ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
            //这里可以不设置。Shiro有默认的session管理。如果缓存为Redis则需改用Redis的管理
           // shiroSessionManager.setSessionDAO(sessionDAO());
            // 自定义sessionFactory
            shiroSessionManager.setSessionFactory(sessionFactory());
            // 加入缓存管理器
            shiroSessionManager.setCacheManager(getEhCacheManager());
            return shiroSessionManager;
        }
    
    
  • 相关阅读:
    September 29th 2017 Week 39th Friday
    September 28th 2017 Week 39th Thursday
    September 27th 2017 Week 39th Wednesday
    September 26th 2017 Week 39th Tuesday
    September 25th 2017 Week 39th Monday
    September 24th 2017 Week 39th Sunday
    angular2 学习笔记 ( Form 表单 )
    angular2 学习笔记 ( Component 组件)
    angular2 学习笔记 ( Http 请求)
    angular2 学习笔记 ( Router 路由 )
  • 原文地址:https://www.cnblogs.com/bug1024/p/11263730.html
Copyright © 2011-2022 走看看