diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/basic/BasicEntryPoint.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/basic/BasicEntryPoint.java index 57aac930..5af105f0 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/basic/BasicEntryPoint.java +++ b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/basic/BasicEntryPoint.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletResponse; import org.maxkey.authn.AbstractAuthenticationProvider; import org.maxkey.constants.ConstantsLoginType; +import org.maxkey.util.AuthorizationHeaderCredential; import org.maxkey.util.AuthorizationHeaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -78,8 +79,6 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor { } } - - // session not exists,session timeout,recreate new session if(request.getSession(false) == null) { _logger.info("recreate new session ."); @@ -95,20 +94,19 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor { _logger.info("Authentication fail header Authorization is null . "); return false; } - String username=null; - String password=null; + + AuthorizationHeaderCredential headerCredential = null; + if(AuthorizationHeaderUtils.isBasic(basicCredential)){ - String []usernamePassword=AuthorizationHeaderUtils.resolveBasic(basicCredential); - username=usernamePassword[0]; - password=usernamePassword[1]; + headerCredential=AuthorizationHeaderUtils.resolve(basicCredential); }else{ return false; } - if(username==null||username.equals("")){ + if(headerCredential.getUsername()==null||headerCredential.getUsername().equals("")){ _logger.info("Authentication fail username is null . "); return false; } - if(password==null||password.equals("")){ + if(headerCredential.getCredential()==null||headerCredential.getCredential().equals("")){ _logger.info("Authentication fail password is null . "); return false; } @@ -123,7 +121,7 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor { UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); String lastSessionUserName = authenticationToken.getPrincipal().toString(); _logger.info("Authentication Principal : " + lastSessionUserName); - if (lastSessionUserName != null && !lastSessionUserName.equals(username)) { + if (lastSessionUserName != null && !lastSessionUserName.equals(headerCredential.getUsername())) { isAuthenticated=false; }else{ isAuthenticated=true; @@ -131,8 +129,8 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor { } if(!isAuthenticated){ - authenticationProvider.trustAuthentication(username,ConstantsLoginType.BASIC,"","","success"); - _logger.info("Authentication "+username+" successful ."); + authenticationProvider.trustAuthentication(headerCredential.getUsername(),ConstantsLoginType.BASIC,"","","success"); + _logger.info("Authentication "+headerCredential.getUsername()+" successful ."); } return true; diff --git a/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderCredential.java b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderCredential.java new file mode 100644 index 00000000..cbb12d07 --- /dev/null +++ b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderCredential.java @@ -0,0 +1,69 @@ +package org.maxkey.util; + +public class AuthorizationHeaderCredential { + + public static class Credential{ + + public static final String BASIC = "Basic "; + + public static final String BEARER = "Bearer "; + } + + String credentialType = Credential.BASIC; + String username; + String credential; + String authorization; + + public AuthorizationHeaderCredential(String bearer) { + super(); + this.credential = bearer; + this.credentialType = Credential.BEARER; + } + + + public AuthorizationHeaderCredential(String username, String credential) { + super(); + this.username = username; + this.credential = credential; + } + + public String getCredentialType() { + return credentialType; + } + + public void setCredentialType(String credentialType) { + this.credentialType = credentialType; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getCredential() { + return credential; + } + public void setCredential(String credential) { + this.credential = credential; + } + + public String transform() { + if(credentialType.equalsIgnoreCase(Credential.BASIC)) { + return AuthorizationHeaderUtils.createBasic(username, credential); + }else { + return AuthorizationHeaderUtils.createBearer(credential); + } + } + + + + @Override + public String toString() { + return "AuthorizationHeaderCredential [credentialType=" + credentialType + ", username=" + username + + ", credential=" + credential + "]"; + } + +} diff --git a/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java index d9d8c749..f34fb766 100644 --- a/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java +++ b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java @@ -27,33 +27,33 @@ public class AuthorizationHeaderUtils { public static final String AUTHORIZATION_HEADERNAME = "Authorization"; - public static final String BASIC = "Basic "; - - public static final String BEARER = "Bearer "; - public static String createBasic(String username, String password) { String authUserPass = username + ":" + password; String encodedAuthUserPass = Base64Utils.encode(authUserPass); - return BASIC + encodedAuthUserPass; + return AuthorizationHeaderCredential.Credential.BASIC + encodedAuthUserPass; } - public static String[] resolveBasic(String basic) { - if (isBasic(basic)) { - String[] userPass = basic.split(" "); - String decodeUserPass = Base64Utils.decode(userPass[1]); - return decodeUserPass.split(":"); + public static AuthorizationHeaderCredential resolve(String authorization) { + if (isBasic(authorization)) { + String decodeUserPass = Base64Utils.decode(authorization.split(" ")[1]); + String []userPass =decodeUserPass.split(":"); + return new AuthorizationHeaderCredential(userPass[0],userPass[1]); } else { - return null; + return new AuthorizationHeaderCredential(resolveBearer(authorization)); } } public static boolean isBasic(String basic) { - if (basic.startsWith(BASIC)) { + if (basic.startsWith(AuthorizationHeaderCredential.Credential.BASIC)) { return true; } else { return false; } } + + public static String createBearer(String bearer) { + return AuthorizationHeaderCredential.Credential.BEARER + bearer; + } public static String resolveBearer(String bearer) { if (isBearer(bearer)) { @@ -62,13 +62,9 @@ public class AuthorizationHeaderUtils { return null; } } - - public static String createBearer(String bearer) { - return BEARER + bearer; - } - + public static boolean isBearer(String bearer) { - if (bearer.startsWith(BEARER)) { + if (bearer.startsWith(AuthorizationHeaderCredential.Credential.BEARER)) { return true; } else { return false; diff --git a/maxkey-common/src/test/java/org/maxkey/rest/AuthorizationHeaderTest.java b/maxkey-common/src/test/java/org/maxkey/rest/AuthorizationHeaderTest.java index ba686b57..d668ea1c 100644 --- a/maxkey-common/src/test/java/org/maxkey/rest/AuthorizationHeaderTest.java +++ b/maxkey-common/src/test/java/org/maxkey/rest/AuthorizationHeaderTest.java @@ -18,15 +18,24 @@ package org.maxkey.rest; import org.junit.Test; +import org.maxkey.util.AuthorizationHeaderCredential; import org.maxkey.util.AuthorizationHeaderUtils; public class AuthorizationHeaderTest { @Test public void test() { + String basic =AuthorizationHeaderUtils.createBasic("Aladdin", "open sesame"); System.out.println(basic); - String []rb=AuthorizationHeaderUtils.resolveBasic(basic); - System.out.println(rb[0]+":"+rb[1]); + + String ahc_basic ="Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; + System.out.println(AuthorizationHeaderUtils.resolve(ahc_basic)); + + AuthorizationHeaderCredential ahc =new AuthorizationHeaderCredential("Aladdin"); + System.out.println(ahc.transform()); + + System.out.println(AuthorizationHeaderUtils.resolve(ahc.transform())); + } } diff --git a/maxkey-web-manage/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java b/maxkey-web-manage/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java index 6d6966bf..18493f9b 100644 --- a/maxkey-web-manage/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java +++ b/maxkey-web-manage/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java @@ -17,14 +17,20 @@ package org.maxkey.web.interceptor; +import java.time.Duration; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.ehcache.UserManagedCache; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.UserManagedCacheBuilder; +import org.maxkey.constants.ConstantsTimeInterval; import org.maxkey.crypto.password.PasswordReciprocal; import org.maxkey.domain.apps.Apps; import org.maxkey.persistence.service.AppsService; +import org.maxkey.util.AuthorizationHeaderCredential; import org.maxkey.util.AuthorizationHeaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,6 +48,15 @@ import org.springframework.web.servlet.AsyncHandlerInterceptor; public class RestApiPermissionAdapter implements AsyncHandlerInterceptor { private static final Logger _logger = LoggerFactory.getLogger(RestApiPermissionAdapter.class); + protected static final UserManagedCache appsCacheStore = + UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Apps.class) + .withExpiry( + ExpiryPolicyBuilder.timeToLiveExpiration( + Duration.ofMinutes(ConstantsTimeInterval.ONE_HOUR) + ) + ) + .build(true); + @Autowired AppsService appsService; @@ -61,15 +76,21 @@ public class RestApiPermissionAdapter implements AsyncHandlerInterceptor { _logger.trace("RestApiPermissionAdapter preHandle"); String authorization = request.getHeader(AuthorizationHeaderUtils.AUTHORIZATION_HEADERNAME); - String [] basicUserPass = AuthorizationHeaderUtils.resolveBasic(authorization); + AuthorizationHeaderCredential headerCredential = AuthorizationHeaderUtils.resolve(authorization); //判断应用的AppId和Secret - if(basicUserPass != null && basicUserPass.length==2){ - _logger.trace(""+ basicUserPass[0]+":"+basicUserPass[1]); - Apps app = appsService.get(basicUserPass[0]); + if(headerCredential != null){ + String appId = headerCredential.getUsername(); + String appSecret = headerCredential.getCredential(); + _logger.trace("appId "+ appId+" , appSecret " + appSecret); + Apps app = appsCacheStore.get(appId); + if (app == null) { + app = appsService.get(appId); + appsCacheStore.put(appId, app); + } _logger.debug("App Info "+ app.getSecret()); - if(app != null && passwordReciprocal.encode(basicUserPass[1]).equalsIgnoreCase(app.getSecret())) { + if(app != null && passwordReciprocal.matches(appSecret, app.getSecret())) { return true; } }