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