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;
        }
    
    
  • 相关阅读:
    OCP-1Z0-052-V8.02-116题
    OCP-1Z0-052-V8.02-6题
    OCP-1Z0-052-V8.02-5题
    使用rman恢复控制文件
    Matlab-质点的运动
    Matlab中checkerboard-创建棋盘图像(二)
    OCP-1Z0-052-V8.02-4题
    OCP-1Z0-052-V8.02-3题
    Matlab中checkerboard-创建棋盘图像(一)
    OCP-1Z0-052-V8.02-1题
  • 原文地址:https://www.cnblogs.com/bug1024/p/11263730.html
Copyright © 2011-2022 走看看