Shiro 요청 헤더 에서 sessionId 및 rememberMe 정 보 를 가 져 옵 니 다.

29935 단어 shiro
본 논문 에서 소개 한 내용 은 Shiro 에 대해 어느 정도 알 아야 합 니 다. Shiro 를 배우 면 개 도 를 볼 수 있 고 저 는 Shiro 를 배 울 수 있 습 니 다.
문제 해결 절차
  • 다시 쓰기 DefaultWebSessionManager 이름 은 DefaultHeaderSessionManager 입 니 다.
  • 다시 쓰기 CookieRememberMeManager 이름 은 HeaderRememberMeManager 입 니 다.
  • 다시 쓰기 ShiroFilterFactoryBean, 기본 Filters 수정;
  • 프로필 을 수정 하여 재 작성 클래스 로 지정 합 니 다.

  • 기본 웹 세 션 관리자 다시 쓰기
    Default WebSession Manager: 웹 환경의 실현 에 사용 되 며, ServletContainer Session Manager 를 대체 하여 세 션 을 유지 하고 있 으 며, Servlet 용기 의 세 션 관 리 를 직접 폐기 합 니 다.Default WebSessionManager 기본 구현 에 서 는 Cookie 를 통 해 sessionId 를 확인 하고 다시 쓸 때 sessionid 를 가 져 오 는 방식 을 request header 에서 가 져 오 는 것 으로 변경 하면 됩 니 다.새 DefaultHeaderSessionManager 클래스 및 extends DefaultSessionManager 및 implements WebSessionManager
    //   import   
    /**
     * @author Created by yangyang on 2018/1/18.
     * e-mail :[email protected] ; tel :18580128658 ;QQ :296604153
     */
    public class DefaultHeaderSessionManager extends DefaultSessionManager implements WebSessionManager {
    
    }

    request header 에서 저 는 x - auth - token 을 사용 하여 sessionid 표 지 를 하고 현재 클래스 의 상세 한 실현 을 직접 보 여 드 리 겠 습 니 다.
    //   import   
    public class DefaultHeaderSessionManager extends DefaultSessionManager implements WebSessionManager {
    
        // slf4j  logback
        private static final Logger log = LoggerFactory.getLogger(DefaultHeaderSessionManager.class);
    
        private final String X_AUTH_TOKEN = "x-auth-token";
    
        //        sessionId   sessionId    response  
        private String getSessionIdHeaderValue(ServletRequest request, ServletResponse response) {
            if (!(request instanceof HttpServletRequest)) {
                log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie.  Returning null.");
                return null;
            } else {
                HttpServletRequest httpRequest = (HttpServletRequest) request;
    
                //  request      x-auth-token        sessionId
    
                String sessionId = httpRequest.getHeader(this.X_AUTH_TOKEN);
    
                //              sessionId    response  
    
                HttpServletResponse httpResponse = (HttpServletResponse) response;
    
                if (StringUtils.isNotEmpty(sessionId)) {
                    httpResponse.setHeader(this.X_AUTH_TOKEN, sessionId);
                    log.info("Current session ID is {}", sessionId);
                }
    
                return sessionId;
            }
        }
    
        //  sessionid
        private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
            String id = this.getSessionIdHeaderValue(request, response);
    
            //DefaultWebSessionManager       copy  
            if (id != null) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            }
            //   sessionid  URL 
            request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, Boolean.FALSE);
            return id;
        }
    
        //   sessionid      deleteMe   
        private void removeSessionIdHeader(HttpServletRequest request, HttpServletResponse response) {
            response.setHeader(this.X_AUTH_TOKEN, "deleteMe");
        }
    
        /**
         *  sessionId    response header  
         * onStart   
         *   sessionid     sessionid     response header 
         */
        private void storeSessionId(Serializable currentId, HttpServletRequest ignored, HttpServletResponse response) {
            if (currentId == null) {
                String msg = "sessionId cannot be null when persisting for subsequent requests.";
                throw new IllegalArgumentException(msg);
            } else {
                String idString = currentId.toString();
    
                response.setHeader(this.X_AUTH_TOKEN, idString);
    
                log.info("Set session ID header for session with id {}", idString);
    
                log.trace("Set session ID header for session with id {}", idString);
            }
        }
    
        //   session
        protected Session createExposedSession(Session session, SessionContext context) {
            if (!WebUtils.isWeb(context)) {
                return super.createExposedSession(session, context);
            } else {
                ServletRequest request = WebUtils.getRequest(context);
                ServletResponse response = WebUtils.getResponse(context);
                SessionKey key = new WebSessionKey(session.getId(), request, response);
                return new DelegatingSession(this, key);
            }
        }
    
        protected Session createExposedSession(Session session, SessionKey key) {
            if (!WebUtils.isWeb(key)) {
                return super.createExposedSession(session, key);
            } else {
                ServletRequest request = WebUtils.getRequest(key);
                ServletResponse response = WebUtils.getResponse(key);
                SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);
                return new DelegatingSession(this, sessionKey);
            }
        }
    
        protected void onStart(Session session, SessionContext context) {
            super.onStart(session, context);
            if (!WebUtils.isHttp(context)) {
                log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response pair. No session ID cookie will be set.");
            } else {
                HttpServletRequest request = WebUtils.getHttpRequest(context);
                HttpServletResponse response = WebUtils.getHttpResponse(context);
                Serializable sessionId = session.getId();
                this.storeSessionId(sessionId, request, response);
                request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
            }
        }
    
        //  sessionid
        public Serializable getSessionId(SessionKey key) {
            Serializable id = super.getSessionId(key);
            if (id == null && WebUtils.isWeb(key)) {
                ServletRequest request = WebUtils.getRequest(key);
                ServletResponse response = WebUtils.getResponse(key);
                id = this.getSessionId(request, response);
            }
            return id;
        }
    
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
            return this.getReferencedSessionId(request, response);
        }
    
        protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
            super.onExpiration(s, ese, key);
            this.onInvalidation(key);
        }
    
        protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {
            super.onInvalidation(session, ise, key);
            this.onInvalidation(key);
        }
    
        private void onInvalidation(SessionKey key) {
            ServletRequest request = WebUtils.getRequest(key);
            if (request != null) {
                request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID);
            }
    
            if (WebUtils.isHttp(key)) {
                log.debug("Referenced session was invalid.  Removing session ID header.");
                this.removeSessionIdHeader(WebUtils.getHttpRequest(key), WebUtils.getHttpResponse(key));
            } else {
                log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response pair. Session ID cookie will not be removed due to invalidated session.");
            }
    
        }
    
        protected void onStop(Session session, SessionKey key) {
            super.onStop(session, key);
            if (WebUtils.isHttp(key)) {
                HttpServletRequest request = WebUtils.getHttpRequest(key);
                HttpServletResponse response = WebUtils.getHttpResponse(key);
                log.debug("Session has been stopped (subject logout or explicit stop).  Removing session ID cookie.");
                this.removeSessionIdHeader(request, response);
            } else {
                log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response pair. Session ID cookie will not be removed due to stopped session.");
            }
        }
    
        public boolean isServletContainerSessions() {
            return false;
        }

    다시 쓰기 CookieRemember MeManger
    기본적으로 Shiro 는 rememberMe 정 보 를 set - cookie 에 넣 고 브 라 우 저 에 저장 합 니 다.여기에 Cookie 방식 을 다시 쓰 고 remembeMe 정 보 를 response header 에 넣 습 니 다.생 성 HeaderRememberMeManager 클래스 및 extends AbstractRememberMeManager, 코드 는 다음 과 같 습 니 다.
    
    //   import   
    public class HeaderRememberMeManager extends AbstractRememberMeManager {
    
        private static final transient Logger log = LoggerFactory.getLogger(HeaderRememberMeManager.class);
    
        // header         key
        public static final String DEFAULT_REMEMBER_ME_HEADER_NAME = "remember-me";
    
    
        protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {
            if (!WebUtils.isHttp(subject)) {
                if (log.isDebugEnabled()) {
                    String msg = "Subject argument is not an HTTP-aware instance.  This is required to obtain a servlet request and response in order to set the rememberMe cookie. Returning immediately and ignoring rememberMe operation.";
                    log.debug(msg);
                }
    
            } else {
                HttpServletResponse response = WebUtils.getHttpResponse(subject);
                String base64 = Base64.encodeToString(serialized);
                //    rememberMe     response header  
                response.setHeader(DEFAULT_REMEMBER_ME_HEADER_NAME, base64);
            }
        }
    
        private boolean isIdentityRemoved(WebSubjectContext subjectContext) {
            ServletRequest request = subjectContext.resolveServletRequest();
            if (request == null) {
                return false;
            } else {
                Boolean removed = (Boolean) request.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY);
                return removed != null && removed;
            }
        }
    
        protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {
            if (!WebUtils.isHttp(subjectContext)) {
                if (log.isDebugEnabled()) {
                    String msg = "SubjectContext argument is not an HTTP-aware instance.  This is required to obtain a servlet request and response in order to retrieve the rememberMe cookie. Returning immediately and ignoring rememberMe operation.";
                    log.debug(msg);
                }
    
                return null;
            } else {
                WebSubjectContext wsc = (WebSubjectContext) subjectContext;
                if (this.isIdentityRemoved(wsc)) {
                    return null;
                } else {
                    HttpServletRequest request = WebUtils.getHttpRequest(wsc);
                    //  request header     rememberMe  
                    String base64 = request.getHeader(DEFAULT_REMEMBER_ME_HEADER_NAME);
                    if ("deleteMe".equals(base64)) {
                        return null;
                    } else if (base64 != null) {
                        base64 = this.ensurePadding(base64);
                        if (log.isTraceEnabled()) {
                            log.trace("Acquired Base64 encoded identity [" + base64 + "]");
                        }
    
                        byte[] decoded = Base64.decode(base64);
                        if (log.isTraceEnabled()) {
                            log.trace("Base64 decoded byte array length: " + (decoded != null ? decoded.length : 0) + " bytes.");
                        }
    
                        return decoded;
                    } else {
                        return null;
                    }
                }
            }
        }
    
        private String ensurePadding(String base64) {
            int length = base64.length();
            if (length % 4 != 0) {
                StringBuilder sb = new StringBuilder(base64);
    
                for (int i = 0; i < length % 4; ++i) {
                    sb.append('=');
                }
    
                base64 = sb.toString();
            }
    
            return base64;
        }
    
        protected void forgetIdentity(Subject subject) {
            if (WebUtils.isHttp(subject)) {
                HttpServletRequest request = WebUtils.getHttpRequest(subject);
                HttpServletResponse response = WebUtils.getHttpResponse(subject);
                this.forgetIdentity(request, response);
            }
    
        }
    
        public void forgetIdentity(SubjectContext subjectContext) {
            if (WebUtils.isHttp(subjectContext)) {
                HttpServletRequest request = WebUtils.getHttpRequest(subjectContext);
                HttpServletResponse response = WebUtils.getHttpResponse(subjectContext);
                this.forgetIdentity(request, response);
            }
        }
    
        private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
        //      
            response.setHeader(DEFAULT_REMEMBER_ME_HEADER_NAME, "deleteMe");
        }
    
    }

    ShiroFilterFactory Bean 다시 쓰기
    기본 Fileter 체인 에서 user 이름 의 필 터 는 로그 인 상태 에서 로그 인 인터페이스 로 돌아 갑 니 다. 로그 인 상 태 를 위해 JSon 문자열 을 직접 넣 고 로그 인 페이지 로 이동 하지 않 아 도 됩 니 다.authc 필 터 를 사용 하면 FormAuthenticationFilter 를 다시 써 야 합 니 다. App 클 라 이언 트 에 맞 게 authc 를 사용 하 는 것 을 추천 하지 않 습 니 다. 사용자 로그 인 정 보 를 다시 검증 해 야 할 때 (remembeMe 정보 로그 인 이 잘못 되 었 습 니 다) 서버 에 미리 요청 하거나 기 록 된 x - auth - token 유효기간 을 통 해 판단 할 수 있 습 니 다.새 MyUserFilter 클래스 extends UserFilter
    public class MyUserFilter extends org.apache.shiro.web.filter.authc.UserFilter {
    
        // isAccessAllowed return false   
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            //               request             request
            this.saveRequest(request);
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.setContentType("application/json;charset=utf-8");
            httpResponse.getWriter().write("{\"code\":-1,\"message\":\"no.login\"}");
            return false;
        }
    
    }

    새로 만 들 기 MyDefaultFilter enum
    //                user        Filter
    //          org.apache.shiro.web.filter.mgt.DefaultFilter
    public enum MyDefaultFilter {
    
        user(MyUserFilter.class);
    
        private final Class extends Filter> filterClass;
    
        private MyDefaultFilter(Class extends Filter> filterClass) {
            this.filterClass = filterClass;
        }
    }

    MyDefaultFilterChainManager 클래스 extends DefaultFilterChainManager
    public class MyDefaultFilterChainManager extends DefaultFilterChainManager {
    
        protected void addDefaultFilters(boolean init) {
    
            //        DefaultFilter
            MyDefaultFilter[] var2 = MyDefaultFilter.values();
            int var3 = var2.length;
    
            for (int var4 = 0; var4 < var3; ++var4) {
                MyDefaultFilter defaultFilter = var2[var4];
                super.addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
            }
    
        }
    
    }

    MyShiroFilterFactoryBean 클래스 extends ShiroFilterFactoryBean
    public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {
    
        protected FilterChainManager createFilterChainManager() {
            //                DefaultFilterChainManager
            MyDefaultFilterChainManager manager = new MyDefaultFilterChainManager();
    
            //         ShiroFilterFactoryBean   copy
        }
        //    private      ShiroFilterFactoryBean   copy
    }

    설정 정보 수정, 재 작성 클래스 가리 키 기
    위 와 관련 된 설정 정보 만 보 여 줍 니 다. 주석 @ Bean 방식 을 사용 합 니 다.
        @Bean(name = "rememberMeManager")
        public HeaderRememberMeManager rememberMeManager() {
            HeaderRememberMeManager headerRememberMeManager = new HeaderRememberMeManager();
            // base64Encoded          rememberMe  
            headerRememberMeManager.setCipherKey(base64Encoded);
            return headerRememberMeManager;
        }
    
        @Bean
        public DefaultHeaderSessionManager defaultWebSessionManager(SessionDAO sessionDAO) {
            DefaultHeaderSessionManager defaultHeaderSessionManager = new DefaultHeaderSessionManager();
            //             session            redis ,    SessionDAO      
            defaultHeaderSessionManager.setSessionValidationSchedulerEnabled(false);
            defaultHeaderSessionManager.setSessionDAO(sessionDAO);
            return defaultHeaderSessionManager;
        }
    
        @Bean(name = "shiroFilter")
        public MyShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
            //         FactoryBean
            MyShiroFilterFactoryBean shiroFilterFactoryBean = new MyShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setFilterChainDefinitions("/api/v1/login = anon
    "
    + "/ = anon
    "
    + "/api/v1/website/article/** = anon
    "
    + "/api/v1/** = cors,user
    "
    ); return shiroFilterFactoryBean; } @Bean(name = "securityManager") public DefaultWebSecurityManager defaultWebSecurityManager( DefaultHeaderSessionManager sessionManager, RememberMeManager rememberMeManager) { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); // //DefaultHeaderSessionManager sessionManager defaultWebSecurityManager.setSessionManager(sessionManager); // rememberMeManager rememberMeManager defaultWebSecurityManager.setRememberMeManager(rememberMeManager); SecurityUtils.setSecurityManager(defaultWebSecurityManager); return defaultWebSecurityManager; }

    이상 의 설정 정 보 를 완성 하면 sessionid 나 remembeMe 를 response header 에 기록 하고 request header 에서 읽 을 수 있 습 니 다. session 시간 초과 자동 소각 시간 전단 은 서버 와 일치 해 야 합 니 다. remembeMe 의 유효 시간 은 전단 에서 자체 적 으로 제어 합 니 다.
    끝나다
    본 고 는 일부 항목 에서 shiro 를 사용 하 는 기 교 를 소개 했다. 만약 에 잘못 되 거나 더 좋 은 방식 이 있 으 면 필자 와 연락 하고 싶다. 필 자 는 QQ: 296604153.

    좋은 웹페이지 즐겨찾기