Shiro 요청 헤더 에서 sessionId 및 rememberMe 정 보 를 가 져 옵 니 다.
                                            
 29935 단어  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 UserFilterpublic 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 DefaultFilterChainManagerpublic 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 ShiroFilterFactoryBeanpublic 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.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
shiro 권한 부여Shiro 는 세 가지 방식 의 인증 을 지원 합 니 다. 본 교육 프로그램 은 첫 번 째 프로 그래 밍 방식 을 사용 하고 실제 와 웹 시스템 을 통합 하여 사용 한 후 두 가지 방식 을 사용 하도록 권한 을 부여...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.