package com.hwlcn.security.web.mgt;
import com.hwlcn.security.codec.Base64;
import com.hwlcn.security.mgt.AbstractRememberMeManager;
import com.hwlcn.security.subject.Subject;
import com.hwlcn.security.subject.SubjectContext;
import com.hwlcn.security.web.servlet.Cookie;
import com.hwlcn.security.web.servlet.SecurityHttpServletRequest;
import com.hwlcn.security.web.servlet.SimpleCookie;
import com.hwlcn.security.web.subject.WebSubjectContext;
import com.hwlcn.security.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieRememberMeManager extends AbstractRememberMeManager {
private static transient final Logger log = LoggerFactory.getLogger(CookieRememberMeManager.class);
public static final String DEFAULT_REMEMBER_ME_COOKIE_NAME = "rememberMe";
private Cookie cookie;
public CookieRememberMeManager() {
Cookie cookie = new SimpleCookie(DEFAULT_REMEMBER_ME_COOKIE_NAME);
cookie.setHttpOnly(true);
cookie.setMaxAge(Cookie.ONE_YEAR);
this.cookie = cookie;
}
public Cookie getCookie() {
return cookie;
}
public void setCookie(Cookie cookie) {
this.cookie = cookie;
}
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);
}
return;
}
HttpServletRequest request = WebUtils.getHttpRequest(subject);
HttpServletResponse response = WebUtils.getHttpResponse(subject);
String base64 = Base64.encodeToString(serialized);
Cookie template = getCookie();
Cookie cookie = new SimpleCookie(template);
cookie.setValue(base64);
cookie.saveTo(request, response);
}
private boolean isIdentityRemoved(WebSubjectContext subjectContext) {
ServletRequest request = subjectContext.resolveServletRequest();
if (request != null) {
Boolean removed = (Boolean) request.getAttribute(SecurityHttpServletRequest.IDENTITY_REMOVED_KEY);
return removed != null && removed;
}
return false;
}
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;
}
WebSubjectContext wsc = (WebSubjectContext) subjectContext;
if (isIdentityRemoved(wsc)) {
return null;
}
HttpServletRequest request = WebUtils.getHttpRequest(wsc);
HttpServletResponse response = WebUtils.getHttpResponse(wsc);
String base64 = getCookie().readValue(request, response);
if (Cookie.DELETED_COOKIE_VALUE.equals(base64)) return null;
if (base64 != null) {
base64 = 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);
forgetIdentity(request, response);
}
}
public void forgetIdentity(SubjectContext subjectContext) {
if (WebUtils.isHttp(subjectContext)) {
HttpServletRequest request = WebUtils.getHttpRequest(subjectContext);
HttpServletResponse response = WebUtils.getHttpResponse(subjectContext);
forgetIdentity(request, response);
}
}
private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
getCookie().removeFrom(request, response);
}
}