RefreshToken

This commit is contained in:
MaxKey
2022-04-30 11:15:16 +08:00
parent 69aa4f27ad
commit eb748ac827
61 changed files with 542 additions and 342 deletions

View File

@@ -19,7 +19,7 @@ package org.maxkey.authn;
import java.util.ArrayList;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.session.Session;
import org.maxkey.authn.session.SessionManager;
@@ -69,7 +69,7 @@ public abstract class AbstractAuthenticationProvider {
protected SessionManager sessionManager;
protected AuthJwtService authJwtService;
protected AuthTokenService authTokenService;
public static ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>();

View File

@@ -31,6 +31,7 @@ public class AuthJwt implements Serializable {
private String ticket;
private String token;
private String refreshToken;
private String type = "Bearer";
private String remeberMe;
private String id;
@@ -57,10 +58,11 @@ public class AuthJwt implements Serializable {
this.authorities = authorities;
}
public AuthJwt(String token, Authentication authentication) {
public AuthJwt(String token,String refreshToken, Authentication authentication) {
SignPrincipal principal = ((SignPrincipal)authentication.getPrincipal());
this.token = token;
this.refreshToken = refreshToken;
this.ticket = principal.getSession().getId();
this.id = principal.getUserInfo().getId();
@@ -166,6 +168,14 @@ public class AuthJwt implements Serializable {
this.remeberMe = remeberMe;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();

View File

@@ -1,99 +1,42 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.jwt;
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.maxkey.authn.SignPrincipal;
import org.maxkey.configuration.AuthJwkConfig;
import org.maxkey.crypto.jwt.HMAC512Service;
import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
public class AuthJwtService {
private static final Logger _logger =
LoggerFactory.getLogger(AuthJwtService.class);
private static final Logger _logger = LoggerFactory.getLogger(AuthJwtService.class);
HMAC512Service hmac512Service;
AuthJwkConfig authJwkConfig;
CongressService congressService;
MomentaryService momentaryService;
public AuthJwtService(AuthJwkConfig authJwkConfig) throws JOSEException {
this.authJwkConfig = authJwkConfig;
this.hmac512Service = new HMAC512Service(authJwkConfig.getSecret());
}
public AuthJwtService(AuthJwkConfig authJwkConfig,CongressService congressService,MomentaryService momentaryService) throws JOSEException {
this.authJwkConfig = authJwkConfig;
this.congressService = congressService;
this.momentaryService = momentaryService;
this.hmac512Service = new HMAC512Service(authJwkConfig.getSecret());
}
/**
* create AuthJwt use Authentication JWT
* @param authentication
* @return AuthJwt
*/
public AuthJwt genAuthJwt(Authentication authentication) {
if(authentication != null) {
return new AuthJwt(genJwt(authentication), authentication);
}
return null;
}
/**
* JWT with Authentication
* @param authentication
* @return
*/
public String genJwt(Authentication authentication) {
public String genJwt(Authentication authentication,String issuer,int expires) {
SignPrincipal principal = ((SignPrincipal)authentication.getPrincipal());
UserInfo userInfo = principal.getUserInfo();
DateTime currentDateTime = DateTime.now();
Date expirationTime = currentDateTime.plusSeconds(authJwkConfig.getExpires()).toDate();
_logger.debug("expiration Time : {}" , expirationTime);
String subject = principal.getUsername();
_logger.trace("jwt subject : {}" , subject);
Date expirationTime = currentDateTime.plusSeconds(expires).toDate();
_logger.debug("jwt subject : {} , expiration Time : {}" , subject,expirationTime);
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
.issuer(authJwkConfig.getIssuer())
.issuer(issuer)
.subject(subject)
.jwtID(principal.getSession().getId())
.issueTime(currentDateTime.toDate())
@@ -111,14 +54,13 @@ public class AuthJwtService {
* @param subject subject
* @return
*/
public String genJwt(String subject) {
public String genJwt(String subject,String issuer,int expires) {
DateTime currentDateTime = DateTime.now();
Date expirationTime = currentDateTime.plusSeconds(authJwkConfig.getExpires()).toDate();
_logger.debug("expiration Time : {}" , expirationTime);
_logger.trace("jwt subject : {}" , subject);
Date expirationTime = currentDateTime.plusSeconds(expires).toDate();
_logger.trace("jwt subject : {} , expiration Time : {}" , subject,expirationTime);
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
.issuer(authJwkConfig.getIssuer())
.issuer(issuer)
.subject(subject)
.jwtID(WebContext.genId())
.issueTime(currentDateTime.toDate())
@@ -132,10 +74,9 @@ public class AuthJwtService {
* Random JWT
* @return
*/
public String genJwt() {
DateTime currentDateTime = DateTime.now();
Date expirationTime = currentDateTime.plusSeconds(authJwkConfig.getExpires()).toDate();
_logger.debug("expiration Time : {}" , expirationTime);
public String genRandomJwt(int expires) {
Date expirationTime = DateTime.now().plusSeconds(expires).toDate();
_logger.trace("expiration Time : {}" , expirationTime);
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
.jwtID(WebContext.genId())
@@ -153,8 +94,25 @@ public class AuthJwtService {
return hmac512Service.sign(jwtToken.getPayload());
}
/**
* Verify with HMAC512 and check ExpirationTime
*
* @param authToken
* @return true or false
*/
public boolean validateJwtToken(String authToken) {
return hmac512Service.verify(authToken);
try {
JWTClaimsSet claims = resolve(authToken);
boolean isExpiration = claims.getExpirationTime().after(DateTime.now().toDate());
boolean isVerify = hmac512Service.verify(authToken);
_logger.debug("JWT Verify {} , now {} , ExpirationTime {} , isExpiration : {}" ,
isVerify,DateTime.now().toDate(),claims.getExpirationTime(),isExpiration);
return isVerify && isExpiration;
} catch (ParseException e) {
_logger.error("authToken {}",authToken);
_logger.error("ParseException ",e);
}
return false;
}
public JWTClaimsSet resolve(String authToken) throws ParseException {
@@ -167,38 +125,4 @@ public class AuthJwtService {
JWTClaimsSet claims = resolve(authToken);
return claims.getJWTID();
}
public String createCongress(Authentication authentication) {
String congress = WebContext.genId();
congressService.store(
congress,
new AuthJwt(
genJwt(authentication),
authentication)
);
return congress;
}
public AuthJwt consumeCongress(String congress) {
AuthJwt authJwt = congressService.consume(congress);
return authJwt;
}
public boolean validateCaptcha(String state,String captcha) {
try {
String jwtId = resolveJWTID(state);
if(StringUtils.isNotBlank(jwtId) &&StringUtils.isNotBlank(captcha)) {
Object momentaryCaptcha = momentaryService.get("", jwtId);
_logger.debug("captcha : {}, momentary Captcha : {}" ,captcha, momentaryCaptcha);
if (!StringUtils.isBlank(captcha) && captcha.equals(momentaryCaptcha.toString())) {
momentaryService.remove("", jwtId);
return true;
}
}
} catch (ParseException e) {
_logger.debug("Exception ",e);
}
return false;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.jwt;
import org.maxkey.configuration.AuthJwkConfig;
import org.maxkey.crypto.jwt.HMAC512Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import com.nimbusds.jose.JOSEException;
public class AuthRefreshTokenService extends AuthJwtService{
private static final Logger _logger = LoggerFactory.getLogger(AuthRefreshTokenService.class);
AuthJwkConfig authJwkConfig;
public AuthRefreshTokenService(AuthJwkConfig authJwkConfig) throws JOSEException {
this.authJwkConfig = authJwkConfig;
this.hmac512Service = new HMAC512Service(authJwkConfig.getRefreshSecret());
}
/**
* JWT Refresh Token with Authentication
* @param authentication
* @return
*/
public String genRefreshToken(Authentication authentication) {
_logger.trace("gen Refresh Token");
return genJwt(
authentication,
authJwkConfig.getIssuer(),
authJwkConfig.getRefreshExpires());
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.jwt;
import java.text.ParseException;
import org.apache.commons.lang3.StringUtils;
import org.maxkey.configuration.AuthJwkConfig;
import org.maxkey.crypto.jwt.HMAC512Service;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import com.nimbusds.jose.JOSEException;
public class AuthTokenService extends AuthJwtService{
private static final Logger _logger = LoggerFactory.getLogger(AuthTokenService.class);
AuthJwkConfig authJwkConfig;
CongressService congressService;
MomentaryService momentaryService;
AuthRefreshTokenService refreshTokenService;
public AuthTokenService(
AuthJwkConfig authJwkConfig,
CongressService congressService,
MomentaryService momentaryService,
AuthRefreshTokenService refreshTokenService) throws JOSEException {
this.authJwkConfig = authJwkConfig;
this.congressService = congressService;
this.momentaryService = momentaryService;
this.refreshTokenService = refreshTokenService;
this.hmac512Service = new HMAC512Service(authJwkConfig.getSecret());
}
/**
* create AuthJwt use Authentication JWT
* @param authentication
* @return AuthJwt
*/
public AuthJwt genAuthJwt(Authentication authentication) {
if(authentication != null) {
String refreshToken = refreshTokenService.genRefreshToken(authentication);
return new AuthJwt(genJwt(authentication),refreshToken, authentication);
}
return null;
}
public String genJwt(Authentication authentication) {
return genJwt( authentication,authJwkConfig.getIssuer(),authJwkConfig.getExpires());
}
/**
* JWT with subject
* @param subject subject
* @return
*/
public String genJwt(String subject) {
return genJwt(subject,authJwkConfig.getIssuer(),authJwkConfig.getExpires());
}
/**
* Random JWT
* @return
*/
public String genRandomJwt() {
return genRandomJwt(authJwkConfig.getExpires());
}
public String createCongress(Authentication authentication) {
String congress = WebContext.genId();
String refreshToken = refreshTokenService.genRefreshToken(authentication);
congressService.store(
congress,
new AuthJwt(
genJwt(authentication),
refreshToken,
authentication)
);
return congress;
}
public AuthJwt consumeCongress(String congress) {
AuthJwt authJwt = congressService.consume(congress);
return authJwt;
}
public boolean validateCaptcha(String state,String captcha) {
try {
String jwtId = resolveJWTID(state);
if(StringUtils.isNotBlank(jwtId) &&StringUtils.isNotBlank(captcha)) {
Object momentaryCaptcha = momentaryService.get("", jwtId);
_logger.debug("captcha : {}, momentary Captcha : {}" ,captcha, momentaryCaptcha);
if (!StringUtils.isBlank(captcha) && captcha.equals(momentaryCaptcha.toString())) {
momentaryService.remove("", jwtId);
return true;
}
}
} catch (ParseException e) {
_logger.debug("Exception ",e);
}
return false;
}
}

View File

@@ -19,7 +19,7 @@ package org.maxkey.authn.provider;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.configuration.ApplicationConfig;
@@ -58,11 +58,11 @@ public class MfaAuthenticationProvider extends AbstractAuthenticationProvider {
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
SessionManager sessionManager,
AuthJwtService authJwtService) {
AuthTokenService authTokenService) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.sessionManager = sessionManager;
this.authJwtService = authJwtService;
this.authTokenService = authTokenService;
}
@Override

View File

@@ -20,7 +20,7 @@ package org.maxkey.authn.provider;
import java.text.ParseException;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.configuration.ApplicationConfig;
@@ -58,11 +58,11 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
SessionManager sessionManager,
AuthJwtService authJwtService) {
AuthTokenService authTokenService) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.sessionManager = sessionManager;
this.authJwtService = authJwtService;
this.authTokenService = authTokenService;
}
@Override
@@ -134,7 +134,7 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
*/
protected void captchaValid(String state ,String captcha) throws ParseException {
// for basic
if(!authJwtService.validateCaptcha(state,captcha)) {
if(!authTokenService.validateCaptcha(state,captcha)) {
throw new BadCredentialsException(WebContext.getI18nValue("login.error.captcha"));
}
}

View File

@@ -110,13 +110,13 @@ public class AbstractSessionManager implements SessionManager{
}
@Override
public void refresh(String sessionId, LocalTime refreshTime) {
public Session refresh(String sessionId, LocalTime refreshTime) {
return null;
}
@Override
public void refresh(String sessionId) {
public Session refresh(String sessionId) {
return null;
}
@Override

View File

@@ -78,14 +78,15 @@ public class InMemorySessionManager extends AbstractSessionManager{
}
@Override
public void refresh(String sessionId,LocalTime refreshTime) {
public Session refresh(String sessionId,LocalTime refreshTime) {
Session session = get(sessionId);
session.setLastAccessTime(refreshTime);
create(sessionId , session);
return session;
}
@Override
public void refresh(String sessionId) {
public Session refresh(String sessionId) {
Session session = get(sessionId);
LocalTime currentTime = LocalTime.now();
@@ -95,8 +96,9 @@ public class InMemorySessionManager extends AbstractSessionManager{
if(duration.getSeconds() > Session.MAX_EXPIRY_DURATION) {
session.setLastAccessTime(currentTime);
refresh(sessionId,currentTime);
return refresh(sessionId,currentTime);
}
return session;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,11 @@ public class RedisSessionManager extends AbstractSessionManager {
RedisConnectionFactory connectionFactory;
public static String PREFIX="REDIS_SESSION_";
public String getKey(String sessionId) {
return PREFIX + sessionId;
}
/**
* @param connectionFactory
*/
@@ -59,15 +64,15 @@ public class RedisSessionManager extends AbstractSessionManager {
@Override
public void create(String sessionId, Session session) {
RedisConnection conn = connectionFactory.getConnection();
conn.setexObject(PREFIX + sessionId, validitySeconds, session);
conn.setexObject( getKey(sessionId), validitySeconds, session);
conn.close();
}
@Override
public Session remove(String sessionId) {
RedisConnection conn=connectionFactory.getConnection();
Session ticket = conn.getObject(PREFIX+sessionId);
conn.delete(PREFIX+sessionId);
Session ticket = conn.getObject(getKey(sessionId));
conn.delete(getKey(sessionId));
conn.close();
return ticket;
}
@@ -75,7 +80,7 @@ public class RedisSessionManager extends AbstractSessionManager {
@Override
public Session get(String sessionId) {
RedisConnection conn=connectionFactory.getConnection();
Session session = conn.getObject(PREFIX+sessionId);
Session session = conn.getObject(getKey(sessionId));
conn.close();
return session;
}
@@ -90,14 +95,15 @@ public class RedisSessionManager extends AbstractSessionManager {
}
@Override
public void refresh(String sessionId,LocalTime refreshTime) {
public Session refresh(String sessionId,LocalTime refreshTime) {
Session session = get(sessionId);
session.setLastAccessTime(refreshTime);
create(sessionId , session);
return session;
}
@Override
public void refresh(String sessionId) {
public Session refresh(String sessionId) {
Session session = get(sessionId);
LocalTime currentTime = LocalTime.now();
@@ -107,8 +113,9 @@ public class RedisSessionManager extends AbstractSessionManager {
if(duration.getSeconds() > Session.MAX_EXPIRY_DURATION) {
session.setLastAccessTime(currentTime);
refresh(sessionId,currentTime);
return refresh(sessionId,currentTime);
}
return session;
}

View File

@@ -30,7 +30,7 @@ public class Session implements Serializable{
public static final String SESSION_PREFIX = "OT";
public static final int MAX_EXPIRY_DURATION = 60 * 10; //default 10 minutes.
public static final int MAX_EXPIRY_DURATION = 60 * 5; //default 5 minutes.
public String id;

View File

@@ -30,9 +30,9 @@ public interface SessionManager {
public Session get(String sessionId);
public void refresh(String sessionId ,LocalTime refreshTime);
public Session refresh(String sessionId ,LocalTime refreshTime);
public void refresh(String sessionId);
public Session refresh(String sessionId);
public void setValiditySeconds(int validitySeconds);

View File

@@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.maxkey.authn.SignPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.crypto.jwt.HMAC512Service;
import org.maxkey.entity.UserInfo;
@@ -36,14 +36,14 @@ import org.springframework.security.core.Authentication;
import com.nimbusds.jwt.JWTClaimsSet;
public abstract class AbstractRemeberMeService {
private static final Logger _logger = LoggerFactory.getLogger(AbstractRemeberMeService.class);
public abstract class AbstractRemeberMeManager {
private static final Logger _logger = LoggerFactory.getLogger(AbstractRemeberMeManager.class);
protected Integer validity = 7;
protected ApplicationConfig applicationConfig;
AuthJwtService authJwtService;
AuthTokenService authTokenService;
// follow function is for persist
public abstract void save(RemeberMe remeberMe);
@@ -90,7 +90,7 @@ public abstract class AbstractRemeberMeService {
}
public RemeberMe resolve(String rememberMeJwt) throws ParseException {
JWTClaimsSet claims = authJwtService.resolve(rememberMeJwt);
JWTClaimsSet claims = authTokenService.resolve(rememberMeJwt);
RemeberMe remeberMe = new RemeberMe();
remeberMe.setId(claims.getJWTID());
remeberMe.setUsername(claims.getSubject());
@@ -109,7 +109,7 @@ public abstract class AbstractRemeberMeService {
.claim("kid", HMAC512Service.MXK_AUTH_JWK)
.build();
return authJwtService.signedJWT(remeberMeJwtClaims);
return authTokenService.signedJWT(remeberMeJwtClaims);
}
public Integer getValidity() {

View File

@@ -24,7 +24,7 @@ import org.maxkey.constants.ConstsTimeInterval;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
public class InMemoryRemeberMeService extends AbstractRemeberMeService {
public class InMemoryRemeberMeManager extends AbstractRemeberMeManager {
protected static final Cache<String, RemeberMe> remeberMeStore =
Caffeine.newBuilder()

View File

@@ -22,15 +22,15 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.configuration.ApplicationConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class JdbcRemeberMeService extends AbstractRemeberMeService {
private static final Logger _logger = LoggerFactory.getLogger(JdbcRemeberMeService.class);
public class JdbcRemeberMeManager extends AbstractRemeberMeManager {
private static final Logger _logger = LoggerFactory.getLogger(JdbcRemeberMeManager.class);
private static final String DEFAULT_DEFAULT_INSERT_STATEMENT =
"insert into mxk_remember_me(id, userid,username,lastlogintime,expirationtime)values( ? , ? , ? , ? , ?)";
@@ -47,14 +47,14 @@ public class JdbcRemeberMeService extends AbstractRemeberMeService {
private final JdbcTemplate jdbcTemplate;
public JdbcRemeberMeService(
public JdbcRemeberMeManager(
JdbcTemplate jdbcTemplate,
ApplicationConfig applicationConfig,
AuthJwtService authJwtService,
AuthTokenService authTokenService,
int validity) {
this.jdbcTemplate = jdbcTemplate;
this.applicationConfig = applicationConfig;
this.authJwtService = authJwtService;
this.authTokenService = authTokenService;
if(validity != 0) {
this.validity = validity;
}

View File

@@ -23,18 +23,18 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
public class RemeberMeServiceFactory {
public class RemeberMeManagerFactory {
private static final Logger _logger =
LoggerFactory.getLogger(RemeberMeServiceFactory.class);
LoggerFactory.getLogger(RemeberMeManagerFactory.class);
public AbstractRemeberMeService getService(
public AbstractRemeberMeManager getService(
int persistence,
JdbcTemplate jdbcTemplate,
RedisConnectionFactory redisConnFactory){
AbstractRemeberMeService remeberMeService = null;
AbstractRemeberMeManager remeberMeService = null;
if (persistence == ConstsPersistence.INMEMORY) {
remeberMeService = new InMemoryRemeberMeService();
remeberMeService = new InMemoryRemeberMeManager();
_logger.debug("InMemoryRemeberMeService");
} else if (persistence == ConstsPersistence.JDBC) {
//remeberMeService = new JdbcRemeberMeService(jdbcTemplate);

View File

@@ -23,7 +23,7 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.maxkey.authn.SignPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.session.Session;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.entity.UserInfo;
@@ -41,43 +41,46 @@ public class AuthorizationUtils {
public static void authenticateWithCookie(
HttpServletRequest request,
AuthJwtService authJwtService,
AuthTokenService authTokenService,
SessionManager sessionManager
) throws ParseException{
if(getAuthentication() == null) {
Cookie authCookie = WebContext.getCookie(request, Authorization_Cookie);
if(authCookie != null ) {
String authorization = authCookie.getValue();
doJwtAuthenticate(authorization,authJwtService,sessionManager);
_logger.debug("congress automatic authenticated .");
}
}
Cookie authCookie = WebContext.getCookie(request, Authorization_Cookie);
if(authCookie != null ) {
String authorization = authCookie.getValue();
doJwtAuthenticate(authorization,authTokenService,sessionManager);
_logger.debug("congress automatic authenticated .");
}
}
public static void authenticate(
HttpServletRequest request,
AuthJwtService authJwtService,
AuthTokenService authTokenService,
SessionManager sessionManager
) throws ParseException{
if(getAuthentication() == null) {
String authorization = AuthorizationHeaderUtils.resolveBearer(request);
if(authorization != null ) {
doJwtAuthenticate(authorization,authJwtService,sessionManager);
_logger.debug("Authorization automatic authenticated .");
}
}
String authorization = AuthorizationHeaderUtils.resolveBearer(request);
if(authorization != null ) {
doJwtAuthenticate(authorization,authTokenService,sessionManager);
_logger.debug("Authorization automatic authenticated .");
}
}
public static void doJwtAuthenticate(
String authorization,
AuthJwtService authJwtService,
AuthTokenService authTokenService,
SessionManager sessionManager) throws ParseException {
if(authJwtService.validateJwtToken(authorization)) {
String sessionId = authJwtService.resolveJWTID(authorization);
Session session = sessionManager.get(sessionId);
if(session != null) {
setAuthentication(session.getAuthentication());
if(authTokenService.validateJwtToken(authorization)) {
if(isNotAuthenticated()) {
String sessionId = authTokenService.resolveJWTID(authorization);
Session session = sessionManager.get(sessionId);
if(session != null) {
setAuthentication(session.getAuthentication());
}else {
setAuthentication(null);
}
}
}else {
setAuthentication(null);
}
}

View File

@@ -0,0 +1,57 @@
package org.maxkey.authn.web;
import org.maxkey.authn.jwt.AuthJwt;
import org.maxkey.authn.jwt.AuthRefreshTokenService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.session.Session;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.entity.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value = "/auth")
public class LoginRefreshPoint {
private static final Logger _logger = LoggerFactory.getLogger(LoginRefreshPoint.class);
@Autowired
AuthTokenService authTokenService;
@Autowired
AuthRefreshTokenService refreshTokenService;
@Autowired
SessionManager sessionManager;
@RequestMapping(value={"/token/refresh"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> refresh(
@RequestHeader(name = "refresh_token", required = true) String refreshToken) {
_logger.trace("refresh token {} " , refreshToken);
try {
if(refreshTokenService.validateJwtToken(refreshToken)) {
String sessionId = refreshTokenService.resolveJWTID(refreshToken);
_logger.trace("Try to refresh sessionId [{}]" , sessionId);
Session session = sessionManager.refresh(sessionId);
if(session != null) {
AuthJwt authJwt = authTokenService.genAuthJwt(session.getAuthentication());
_logger.trace("Grant new token {}" , authJwt);
return new Message<AuthJwt>(authJwt).buildResponse();
}else {
_logger.debug("Session is timeout , sessionId [{}]" , sessionId);
}
}else {
_logger.trace("refresh token is not validate .");
}
}catch(Exception e) {
_logger.error("Refresh Exception !",e);
}
return new ResponseEntity<>("Refresh Token Fail !", HttpStatus.UNAUTHORIZED);
}
}

View File

@@ -35,10 +35,11 @@ import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
@RequestMapping(value = "/auth")
public class UnauthorizedEntryPoint {
private static final Logger _logger = LoggerFactory.getLogger(UnauthorizedEntryPoint.class);
@RequestMapping(value={"/auth/entrypoint"})
@RequestMapping(value={"/entrypoint"})
public void entryPoint(
HttpServletRequest request, HttpServletResponse response)
throws StreamWriteException, DatabindException, IOException {

View File

@@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.maxkey.authn.SignPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.authn.web.AuthorizationUtils;
import org.maxkey.configuration.ApplicationConfig;
@@ -47,7 +47,7 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
SessionManager sessionManager;
@Autowired
AuthJwtService authJwtService ;
AuthTokenService authTokenService ;
boolean mgmt = false;
@@ -59,7 +59,7 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
_logger.trace("Permission Interceptor .");
AuthorizationUtils.authenticate(request, authJwtService, sessionManager);
AuthorizationUtils.authenticate(request, authTokenService, sessionManager);
SignPrincipal principal = AuthorizationUtils.getPrincipal();
//判断用户是否登录,判断用户是否登录用户
if(principal == null){

View File

@@ -19,7 +19,8 @@ package org.maxkey.autoconfigure;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.SavedRequestAwareAuthenticationSuccessHandler;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.AuthRefreshTokenService;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.jwt.CongressService;
import org.maxkey.authn.jwt.InMemoryCongressService;
import org.maxkey.authn.jwt.RedisCongressService;
@@ -30,8 +31,8 @@ import org.maxkey.authn.provider.TrustedAuthenticationProvider;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.session.SessionManager;
import org.maxkey.authn.session.SessionManagerFactory;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
import org.maxkey.authn.support.rememberme.JdbcRemeberMeService;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeManager;
import org.maxkey.authn.support.rememberme.JdbcRemeberMeManager;
import org.maxkey.authn.web.HttpSessionListenerAdapter;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.configuration.AuthJwkConfig;
@@ -89,14 +90,14 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
SessionManager sessionManager,
AuthJwtService authJwtService
AuthTokenService authTokenService
) {
_logger.debug("init authentication Provider .");
return new NormalAuthenticationProvider(
authenticationRealm,
applicationConfig,
sessionManager,
authJwtService
authTokenService
);
}
@@ -131,10 +132,11 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
}
@Bean
public AuthJwtService authJwtService(
public AuthTokenService authTokenService(
AuthJwkConfig authJwkConfig,
RedisConnectionFactory redisConnFactory,
MomentaryService momentaryService,
AuthRefreshTokenService refreshTokenService,
@Value("${maxkey.server.persistence}") int persistence) throws JOSEException {
CongressService congressService;
if (persistence == ConstsPersistence.REDIS) {
@@ -143,9 +145,20 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
congressService = new InMemoryCongressService();
}
AuthJwtService authJwtService = new AuthJwtService(authJwkConfig,congressService,momentaryService);
AuthTokenService authTokenService =
new AuthTokenService(
authJwkConfig,
congressService,
momentaryService,
refreshTokenService
);
return authJwtService;
return authTokenService;
}
@Bean
public AuthRefreshTokenService refreshTokenService(AuthJwkConfig authJwkConfig) throws JOSEException {
return new AuthRefreshTokenService(authJwkConfig);
}
@Bean(name = "otpAuthnService")
@@ -196,21 +209,20 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
return sessionManager;
}
/**
* remeberMeService .
* @return
*/
@Bean
public AbstractRemeberMeService remeberMeService(
public AbstractRemeberMeManager remeberMeManager(
@Value("${maxkey.server.persistence}") int persistence,
@Value("${maxkey.login.remeberme.validity}") int validity,
ApplicationConfig applicationConfig,
AuthJwtService authJwtService,
AuthTokenService authTokenService,
JdbcTemplate jdbcTemplate) {
_logger.trace("init remeberMeService , validity {}." , validity);
return new JdbcRemeberMeService(
jdbcTemplate,applicationConfig,authJwtService,validity);
_logger.trace("init RemeberMeManager , validity {}." , validity);
return new JdbcRemeberMeManager(
jdbcTemplate,applicationConfig,authTokenService,validity);
}
@Bean

View File

@@ -41,7 +41,7 @@ public class JwtAuthnAutoConfiguration implements InitializingBean {
* jwt Login JwkSetKeyStore.
* @return
*/
@Bean(name = "jwtLoginJwkSetKeyStore")
@Bean
public JWKSetKeyStore jwtLoginJwkSetKeyStore() {
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore();
ClassPathResource classPathResource = new ClassPathResource("/config/loginjwkkeystore.jwks");
@@ -57,7 +57,7 @@ public class JwtAuthnAutoConfiguration implements InitializingBean {
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
@Bean(name = "jwtLoginValidationService")
@Bean
public DefaultJwtSigningAndValidationService jwtLoginValidationService(
JWKSetKeyStore jwtLoginJwkSetKeyStore)
throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
@@ -73,7 +73,7 @@ public class JwtAuthnAutoConfiguration implements InitializingBean {
* Jwt LoginService.
* @return
*/
@Bean(name = "jwtLoginService")
@Bean
public JwtLoginService jwtLoginService(
@Value("${maxkey.login.jwt.issuer}")
String issuer,