com.flyfish.oauth.common.auth.OAuthAuthenticator Maven / Gradle / Ivy
package com.flyfish.oauth.common.auth;
import com.flyfish.oauth.common.OAuth2PostAware;
import com.flyfish.oauth.common.OAuthFilterContext;
import com.flyfish.oauth.domain.OAuth2AccessToken;
import com.flyfish.oauth.domain.OAuthSSOToken;
import com.flyfish.oauth.domain.raw.SSOUserInfo;
import com.flyfish.oauth.utils.OAuthRequestParser;
import com.flyfish.oauth.utils.UserConvertUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* 开放认证器
*
* @author wangyu
* 逻辑抽离,便于调用
*/
public class OAuthAuthenticator extends OAuth2PostAware {
// 过滤的资源路径
private static final List RESOURCE_TYPES =
Arrays.asList(".js", ".css", ".ico", ".jpg", ".png", ".svg", ".gif", ".eot", ".ttf", ".woff");
public static OAuthAuthenticator getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 检查请求状态
*
* @param request 请求
* @return 结果
*/
public boolean checkStatus(HttpServletRequest request) {
// 如果是资源文件,或者是跳过的,直接放行,提高性能
return !checkResource(request.getRequestURI()) || checkAllowed(request.getRequestURI(), client.getProperties().getAllowUris());
}
/**
* 鉴权,这里使用请求上下文鉴权
*
* @param context 上下文
* @return 通过与否
*/
public AuthStatus authenticate(OAuthFilterContext context) throws IOException {
HttpServletRequest request = context.getRequest();
HttpServletResponse response = context.getResponse();
// 解析请求
OAuthRequestParser parsed = OAuthRequestParser.parse(request);
// 获取token
String accessToken = parsed.getAccessToken();
// 检查放行规则,如果是认证请求,这里直接放行
if (parsed.isAuthRequest()) {
return AuthStatus.SKIP;
}
// 判断token有效性
boolean tokenValid = accessToken != null && authenticationEntryPoint.checkAccessToken(accessToken);
// 放行,并获取数据
if (tokenValid) {
if (authenticateSuccess(request, accessToken)) {
return AuthStatus.SUCCESS;
}
return AuthStatus.REDIRECT;
} else {
String refreshToken = parsed.getRefreshToken();
// 刷新token
if (refreshAccessToken(response, refreshToken)) {
authenticateSuccess(request, accessToken);
return AuthStatus.SUCCESS;
} else if (parsed.needRedirect() || client.getProperties().isAutoRedirect()) {
// 设定开放认证标识
response.addCookie(new Cookie(OAuth2AccessToken.AUTH_PARAM_VALUE, "1"));
// 登出
authenticationEntryPoint.logout(request);
// token不存在或者无效
response.sendRedirect(authenticationEntryPoint.redirectUrl(parsed));
return AuthStatus.REDIRECT;
}
}
return AuthStatus.FAIL;
}
/**
* 认证成功的回调
*
* @param request 请求
* @param accessToken token
*/
private boolean authenticateSuccess(HttpServletRequest request, String accessToken) {
HttpSession session = request.getSession();
// 自动补全信息
if (!client.getSessionConverter().isComplete(session)) {
SSOUserInfo userInfo = authenticationEntryPoint.getUserInfo(accessToken);
request.setAttribute("user", userInfo);
Object user = UserConvertUtils.convert(client.getUserService(), userInfo);
return client.getSessionConverter().convert(session, user);
}
return true;
}
/**
* 刷新accessToken
*
* @param response 响应
* @param refreshToken 刷新Token
* @return 结果
*/
private boolean refreshAccessToken(HttpServletResponse response, String refreshToken) {
// token无效或者木有,但是refreshToken存在,尝试刷新
if (null != refreshToken) {
OAuthSSOToken refreshedToken = authenticationEntryPoint.refreshAccessToken(refreshToken);
if (null == refreshedToken) {
return false;
}
// 写入Cookie
for (Cookie cookie : refreshedToken.toCookies()) {
response.addCookie(cookie);
}
return true;
}
return false;
}
/**
* 判断当前请求是否是资源请求,如果是,则放行
*
* @return 结果
*/
private boolean checkResource(String requestURI) {
for (String type : RESOURCE_TYPES) {
if (requestURI.endsWith(type)) {
return false;
}
}
return true;
}
/**
* 检查放行规则
*
* @param uri uri
* @param uris uris
* @return 结果
*/
private boolean checkAllowed(String uri, Set uris) {
for (String perUri : uris) {
if (perUri.endsWith("/**") && uri.startsWith(perUri.substring(0, perUri.indexOf("/**"))) || uri.equals(perUri)) {
return true;
}
}
return false;
}
private static class SingletonHolder {
private static final OAuthAuthenticator INSTANCE = new OAuthAuthenticator();
}
}