🎨 SSO supports maxAge of custom cookie. Decoupling fastjson.

This commit is contained in:
yadong.zhang 2021-01-21 16:14:00 +08:00
parent fa9c30c692
commit 6202f83fb3
9 changed files with 60 additions and 36 deletions

View File

@ -15,9 +15,10 @@
*/
package com.fujieid.jap.core;
import com.alibaba.fastjson.JSONObject;
import com.fujieid.jap.core.exception.JapUserException;
import java.util.Map;
/**
* Abstract the user-related function interface, which is implemented by the caller business system.
*
@ -97,7 +98,7 @@ public interface JapUserService {
* @param userInfo The basic user information returned by the OAuth platform
* @return When saving successfully, return {@code JapUser}, otherwise return {@code null}
*/
default JapUser createAndGetOauth2User(String platform, JSONObject userInfo) {
default JapUser createAndGetOauth2User(String platform, Map<String, Object> userInfo) {
throw new JapUserException("JapUserService#createAndGetOauth2User(JSONObject) must be overridden by subclass");
}

View File

@ -23,6 +23,12 @@
<version>${jap.version}</version>
</dependency>
<dependency>
<groupId>com.xkcoding.json</groupId>
<artifactId>simple-json</artifactId>
<version>${simple-json.version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>

View File

@ -20,7 +20,6 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.fujieid.jap.core.AuthenticateConfig;
import com.fujieid.jap.core.JapConfig;
import com.fujieid.jap.core.JapUser;
@ -29,13 +28,13 @@ import com.fujieid.jap.core.exception.JapException;
import com.fujieid.jap.core.exception.JapOauth2Exception;
import com.fujieid.jap.core.exception.JapUserException;
import com.fujieid.jap.core.store.JapUserStore;
import com.fujieid.jap.core.store.SessionJapUserStore;
import com.fujieid.jap.core.strategy.AbstractJapStrategy;
import com.fujieid.jap.oauth2.pkce.PkceCodeChallengeMethod;
import com.fujieid.jap.oauth2.pkce.PkceParams;
import com.fujieid.jap.oauth2.pkce.PkceUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.xkcoding.json.JsonUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -114,10 +113,10 @@ public class Oauth2Strategy extends AbstractJapStrategy {
protected JapUser getUserInfo(OAuthConfig oAuthConfig, String accessToken) {
String userinfoResponse = HttpUtil.post(oAuthConfig.getUserinfoUrl(), ImmutableMap.of("access_token", accessToken));
JSONObject userinfo = JSONObject.parseObject(userinfoResponse);
if (userinfo.containsKey("error") && StrUtil.isNotBlank(userinfo.getString("error"))) {
Map<String, Object> userinfo = JsonUtil.toBean(userinfoResponse, Map.class);
if (userinfo.containsKey("error") && ObjectUtil.isNotEmpty(userinfo.get("error"))) {
throw new JapOauth2Exception("Oauth2Strategy failed to get userinfo with accessToken." +
userinfo.getString("error_description") + " " + userinfoResponse);
userinfo.get("error_description") + " " + userinfoResponse);
}
JapUser japUser = this.japUserService.createAndGetOauth2User(oAuthConfig.getPlatform(), userinfo);
if (ObjectUtil.isNull(japUser)) {
@ -141,10 +140,10 @@ public class Oauth2Strategy extends AbstractJapStrategy {
params.put(PkceParams.CODE_VERIFIER, PkceUtil.getCacheCodeVerifier());
}
String tokenResponse = HttpUtil.post(oAuthConfig.getTokenUrl(), params);
JSONObject accessToken = JSONObject.parseObject(tokenResponse);
if (accessToken.containsKey("error") && StrUtil.isNotBlank(accessToken.getString("error"))) {
Map<String, Object> accessToken = JsonUtil.toBean(tokenResponse, Map.class);
if (accessToken.containsKey("error") && ObjectUtil.isNotEmpty(accessToken.get("error"))) {
throw new JapOauth2Exception("Oauth2Strategy failed to get AccessToken." +
accessToken.getString("error_description") + " " + tokenResponse);
accessToken.get("error_description") + " " + tokenResponse);
}
if (!accessToken.containsKey("access_token")) {
throw new JapOauth2Exception("Oauth2Strategy failed to get AccessToken." + tokenResponse);
@ -158,7 +157,7 @@ public class Oauth2Strategy extends AbstractJapStrategy {
"example_parameter":"example_value"
}
*/
return accessToken.getString("access_token");
return (String) accessToken.get("access_token");
}
protected void redirectToAuthorizationEndPoint(HttpServletResponse response, OAuthConfig oAuthConfig) {
@ -177,7 +176,7 @@ public class Oauth2Strategy extends AbstractJapStrategy {
// Pkce is only applicable to authorization code mode
if (Oauth2ResponseType.code == oAuthConfig.getResponseType() && oAuthConfig.isEnablePkce()) {
PkceUtil.addPkceParameters(Optional.ofNullable(oAuthConfig.getCodeChallengeMethod())
.orElse(PkceCodeChallengeMethod.S256), params);
.orElse(PkceCodeChallengeMethod.S256), params);
}
String query = URLUtil.buildQuery(params, StandardCharsets.UTF_8);
try {

View File

@ -49,7 +49,7 @@ public class OidcStrategy extends Oauth2Strategy {
* @param japConfig japConfig
*/
public OidcStrategy(JapUserService japUserService, JapConfig japConfig) {
super(japUserService, new SessionJapUserStore(), japConfig);
super(japUserService, japConfig);
}
/**

View File

@ -16,11 +16,14 @@
package com.fujieid.jap.oidc;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import com.fujieid.jap.core.exception.OidcException;
import com.xkcoding.json.JsonUtil;
import java.util.Map;
/**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
@ -45,17 +48,17 @@ public class OidcUtil {
String discoveryUrl = issuer.concat(DISCOVERY_URL);
HttpResponse httpResponse = HttpRequest.get(discoveryUrl).execute();
JSONObject jsonObject = JSONObject.parseObject(httpResponse.body());
if (CollectionUtil.isEmpty(jsonObject)) {
Map<String, Object> oidcDiscoveryInfo = JsonUtil.toBean(httpResponse.body(), Map.class);
if (CollectionUtil.isEmpty(oidcDiscoveryInfo)) {
throw new OidcException("Unable to parse IDP service discovery configuration information.");
}
return new OidcDiscoveryDto()
.setIssuer(jsonObject.getString(OidcDiscoveryParams.ISSUER))
.setAuthorizationEndpoint(jsonObject.getString(OidcDiscoveryParams.AUTHORIZATION_ENDPOINT))
.setTokenEndpoint(jsonObject.getString(OidcDiscoveryParams.TOKEN_ENDPOINT))
.setUserinfoEndpoint(jsonObject.getString(OidcDiscoveryParams.USERINFO_ENDPOINT))
.setEndSessionEndpoint(jsonObject.getString(OidcDiscoveryParams.END_SESSION_ENDPOINT))
.setJwksUri(jsonObject.getString(OidcDiscoveryParams.JWKS_URI));
.setIssuer(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.ISSUER)))
.setAuthorizationEndpoint(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.AUTHORIZATION_ENDPOINT)))
.setTokenEndpoint(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.TOKEN_ENDPOINT)))
.setUserinfoEndpoint(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.USERINFO_ENDPOINT)))
.setEndSessionEndpoint(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.END_SESSION_ENDPOINT)))
.setJwksUri(ObjectUtil.toString(oidcDiscoveryInfo.get(OidcDiscoveryParams.JWKS_URI)));
}

View File

@ -15,13 +15,7 @@
Single Sign On
</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>kisso</artifactId>

View File

@ -36,8 +36,8 @@ public class JapSsoHelper {
/**
* Write user information into cookie after successful login
*
* @param userId 当前登录用户的id
* @param username 当前登录用户的name
* @param userId The ID of the current login user
* @param username The name of the current login user
* @param japSsoConfig sso config
* @param request current request
* @param response current response
@ -52,6 +52,7 @@ public class JapSsoHelper {
ssoConfig.setParamReturnUrl(japSsoConfig.getParamReturnUrl());
ssoConfig.setLoginUrl(japSsoConfig.getLoginUrl());
ssoConfig.setLogoutUrl(japSsoConfig.getLogoutUrl());
ssoConfig.setCookieMaxAge(japSsoConfig.getCookieMaxAge());
SSOHelper.setSsoConfig(ssoConfig);
// set jap cookie
SSOHelper.setCookie(request, response,

View File

@ -33,6 +33,10 @@ public class JapSsoConfig {
* The domain name of the cookie. By default, it is the current access domain name.
*/
private String cookieDomain;
/**
* The validity of the cookie
*/
private int cookieMaxAge = Integer.MAX_VALUE;
/**
* Parameter name of callback url after successful login
*/
@ -86,6 +90,15 @@ public class JapSsoConfig {
return this;
}
public int getCookieMaxAge() {
return cookieMaxAge;
}
public JapSsoConfig setCookieMaxAge(int cookieMaxAge) {
this.cookieMaxAge = cookieMaxAge;
return this;
}
public String getLogoutUrl() {
return logoutUrl;
}

19
pom.xml
View File

@ -51,7 +51,6 @@
<jap.version>1.0.0</jap.version>
<junit.version>4.13.1</junit.version>
<fastjson.version>1.2.73</fastjson.version>
<hutool.version>5.5.7</hutool.version>
<guava.version>RELEASE</guava.version>
<javax.servlet.version>4.0.1</javax.servlet.version>
@ -60,6 +59,7 @@
<slf4j-api.version>1.7.30</slf4j-api.version>
<jedis.version>3.2.0</jedis.version>
<kisso.version>3.7.6</kisso.version>
<simple-json.version>0.0.1</simple-json.version>
</properties>
<dependencies>
@ -69,11 +69,6 @@
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@ -99,6 +94,18 @@
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>