3.4.0 with Angular

This commit is contained in:
MaxKey
2022-03-28 22:00:46 +08:00
parent 0526fdcde2
commit 374e16bf5a
1029 changed files with 905 additions and 284771 deletions
@@ -20,7 +20,7 @@ package org.maxkey.authn;
import java.util.ArrayList;
import java.util.HashMap;
import org.maxkey.authn.online.OnlineTicketServices;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
import org.maxkey.configuration.ApplicationConfig;
@@ -64,7 +64,7 @@ public abstract class AbstractAuthenticationProvider {
protected AbstractRemeberMeService remeberMeService;
protected OnlineTicketServices onlineTicketServices;
protected OnlineTicketService onlineTicketServices;
public static ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>();
@@ -380,7 +380,7 @@ public abstract class AbstractAuthenticationProvider {
this.remeberMeService = remeberMeService;
}
public void setOnlineTicketServices(OnlineTicketServices onlineTicketServices) {
public void setOnlineTicketServices(OnlineTicketService onlineTicketServices) {
this.onlineTicketServices = onlineTicketServices;
}
@@ -0,0 +1,13 @@
package org.maxkey.authn;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
}
@@ -0,0 +1,34 @@
package org.maxkey.authn;
import org.maxkey.entity.UserInfo;
import org.maxkey.web.WebConstants;
import org.springframework.core.MethodParameter;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(UserInfo.class)
&& parameter.hasParameterAnnotation(CurrentUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
UserInfo userInfo = null;
Authentication authentication = (Authentication ) webRequest.getAttribute(WebConstants.AUTHENTICATION, RequestAttributes.SCOPE_SESSION);
if(authentication.getPrincipal() instanceof SigninPrincipal) {
SigninPrincipal signinPrincipal = ((SigninPrincipal) authentication.getPrincipal());
userInfo = signinPrincipal.getUserInfo();
if (userInfo != null) {
return userInfo;
}
}
throw new MissingServletRequestPartException("currentUser");
}
}
@@ -20,7 +20,7 @@ package org.maxkey.authn;
import java.util.ArrayList;
import org.maxkey.authn.online.OnlineTicket;
import org.maxkey.authn.online.OnlineTicketServices;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
import org.maxkey.configuration.ApplicationConfig;
@@ -66,7 +66,7 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
AbstractOtpAuthn tfaOtpAuthn,
OtpAuthnService otpAuthnService,
AbstractRemeberMeService remeberMeService,
OnlineTicketServices onlineTicketServices) {
OnlineTicketService onlineTicketServices) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.tfaOtpAuthn = tfaOtpAuthn;
@@ -80,7 +80,7 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
_logger.debug("authentication " + loginCredential);
sessionValid(loginCredential.getSessionId());
//sessionValid(loginCredential.getSessionId());
//jwtTokenValid(j_jwtToken);
@@ -0,0 +1,115 @@
/*
* Copyright [2020] [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.interceptor;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.maxkey.authn.SigninPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.online.OnlineTicket;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.util.AuthorizationHeaderUtils;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
/**
* 权限Interceptor处理
* 权限处理需在servlet.xml中配置
* mvc:interceptors permission
* @author Crystal.Sea
*
*/
@Component
public class PermissionAdapter implements AsyncHandlerInterceptor {
private static final Logger _logger = LoggerFactory.getLogger(PermissionAdapter.class);
//无需Interceptor url
@Autowired
@Qualifier("applicationConfig")
private ApplicationConfig applicationConfig;
@Autowired
@Qualifier("onlineTicketService")
OnlineTicketService onlineTicketService;
@Autowired
@Qualifier("authJwtService")
AuthJwtService authJwtService ;
/*
* 请求前处理
* (non-Javadoc)
* @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
*/
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
_logger.trace("PermissionAdapter preHandle");
String authorization = AuthorizationHeaderUtils.resolveBearer(request);
if(authJwtService.validateJwtToken(authorization)) {
String ticket = authJwtService.resolveTicket(authorization);
if(WebContext.getAuthentication()==null) {
OnlineTicket onlineTicket = onlineTicketService.get(ticket);
if(onlineTicket != null) {
WebContext.setAuthentication(onlineTicket.getAuthentication());
}
}
//判断用户是否登录
if(WebContext.getAuthentication()==null
||WebContext.getAuthentication().getAuthorities()==null){//判断用户和角色,判断用户是否登录用户
_logger.trace("No Authentication ... forward to /login");
RequestDispatcher dispatcher = request.getRequestDispatcher("/login");
dispatcher.forward(request, response);
return false;
}
//非管理员用户直接注销
if (!((SigninPrincipal) WebContext.getAuthentication().getPrincipal()).isRoleAdministrators()) {
_logger.debug("Not ADMINISTRATORS Authentication .");
RequestDispatcher dispatcher = request.getRequestDispatcher("/logout");
dispatcher.forward(request, response);
return false;
}
}
boolean hasAccess=true;
/*
boolean preHandler = super.preHandle(request, response, handler);
if(preHandler) {
preHandler = false;
if(!preHandler){//无权限转向
log.debug("You do not have permission to access "+accessUrl);
RequestDispatcher dispatcher = request.getRequestDispatcher("/accessdeny");
dispatcher.forward(request, response);
return false;
}
}*/
return hasAccess;
}
}
@@ -0,0 +1 @@
package org.maxkey.authn.interceptor;
@@ -0,0 +1,145 @@
package org.maxkey.authn.jwt;
import java.util.ArrayList;
import java.util.List;
import org.maxkey.authn.SigninPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
public class AuthJwt {
private String token;
private String type = "Bearer";
private String id;
private String name;
private String username;
private String displayName;
private String email;
private String instId;
private String instName;
private List<String> authorities;
public AuthJwt(String token, String id, String username, String displayName, String email, String instId,
String instName, List<String> authorities) {
this.token = token;
this.id = id;
this.name = username;
this.username = username;
this.displayName = displayName;
this.email = email;
this.instId = instId;
this.instName = instName;
this.authorities = authorities;
}
public AuthJwt(String token, Authentication authentication) {
SigninPrincipal signinPrincipal = ((SigninPrincipal)authentication.getPrincipal());
this.token = token;
this.id = signinPrincipal.getUserInfo().getId();
this.username = signinPrincipal.getUserInfo().getUsername();
this.name = this.username;
this.displayName = signinPrincipal.getUserInfo().getDisplayName();
this.email = signinPrincipal.getUserInfo().getEmail();
this.instId = signinPrincipal.getUserInfo().getInstId();
this.instName = signinPrincipal.getUserInfo().getInstName();
this.authorities = new ArrayList<String>();
for(GrantedAuthority grantedAuthority :authentication.getAuthorities()) {
this.authorities.add(grantedAuthority.getAuthority());
}
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getInstId() {
return instId;
}
public void setInstId(String instId) {
this.instId = instId;
}
public String getInstName() {
return instName;
}
public void setInstName(String instName) {
this.instName = instName;
}
public List<String> getAuthorities() {
return authorities;
}
public void setAuthorities(List<String> authorities) {
this.authorities = authorities;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("AuthJwt [token=");
builder.append(token);
builder.append(", type=");
builder.append(type);
builder.append(", id=");
builder.append(id);
builder.append(", username=");
builder.append(username);
builder.append(", displayName=");
builder.append(displayName);
builder.append(", email=");
builder.append(email);
builder.append(", instId=");
builder.append(instId);
builder.append(", instName=");
builder.append(instName);
builder.append(", authorities=");
builder.append(authorities);
builder.append("]");
return builder.toString();
}
}
@@ -0,0 +1,81 @@
package org.maxkey.authn.jwt;
import java.text.ParseException;
import java.util.Date;
import org.joda.time.DateTime;
import org.maxkey.authn.SigninPrincipal;
import org.maxkey.configuration.AuthJwkConfig;
import org.maxkey.crypto.jwt.HMAC512Service;
import org.maxkey.entity.UserInfo;
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);
HMAC512Service hmac512Service;
AuthJwkConfig authJwkConfig;
public AuthJwtService(AuthJwkConfig authJwkConfig) throws JOSEException {
this.authJwkConfig = authJwkConfig;
this.hmac512Service = new HMAC512Service(authJwkConfig.getSecret());
}
public String generateToken(Authentication authentication) {
String token = "";
SigninPrincipal signinPrincipal = ((SigninPrincipal)authentication.getPrincipal());
UserInfo userInfo = signinPrincipal.getUserInfo();
DateTime currentDateTime = DateTime.now();
Date expirationTime = currentDateTime.plusSeconds(authJwkConfig.getExpires()).toDate();
_logger.debug("expiration Time : {}" , expirationTime);
String subject = signinPrincipal.getUsername();
_logger.trace("jwt subject : {}" , subject);
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
.issuer(authJwkConfig.getIssuer())
.subject(subject)
.jwtID(signinPrincipal.getOnlineTicket().getTicketId())
.issueTime(currentDateTime.toDate())
.expirationTime(expirationTime)
.claim("locale", userInfo.getLocale())
.claim("kid", HMAC512Service.MXK_AUTH_JWK)
.claim("institution", userInfo.getInstId())
.build();
_logger.trace("jwt Claims : {}" , jwtClaims);
SignedJWT jwtToken = new SignedJWT(
new JWSHeader(JWSAlgorithm.HS512),
jwtClaims);
token = hmac512Service.sign(jwtToken.getPayload());
return token ;
}
public boolean validateJwtToken(String authToken) {
return hmac512Service.verify(authToken);
}
public JWTClaimsSet resolve(String authToken) throws ParseException {
SignedJWT signedJWT = SignedJWT.parse(authToken);
_logger.trace("jwt Claims : {}" , signedJWT.getJWTClaimsSet());
return signedJWT.getJWTClaimsSet();
}
public String resolveTicket(String authToken) throws ParseException {
JWTClaimsSet claims = resolve(authToken);
return claims.getJWTID();
}
}
@@ -0,0 +1 @@
package org.maxkey.authn.jwt;
@@ -28,8 +28,8 @@ import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
public class InMemoryOnlineTicketServices implements OnlineTicketServices{
private static final Logger _logger = LoggerFactory.getLogger(InMemoryOnlineTicketServices.class);
public class InMemoryOnlineTicketService implements OnlineTicketService{
private static final Logger _logger = LoggerFactory.getLogger(InMemoryOnlineTicketService.class);
protected static Cache<String, OnlineTicket> onlineTicketStore =
Caffeine.newBuilder()
@@ -37,7 +37,7 @@ public class InMemoryOnlineTicketServices implements OnlineTicketServices{
.maximumSize(200000)
.build();
public InMemoryOnlineTicketServices() {
public InMemoryOnlineTicketService() {
super();
}
@@ -19,7 +19,7 @@ package org.maxkey.authn.online;
import java.time.LocalTime;
public interface OnlineTicketServices {
public interface OnlineTicketService {
public void store(String ticketId, OnlineTicket ticket);
@@ -23,23 +23,23 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
public class OnlineTicketServicesFactory {
public class OnlineTicketServiceFactory {
private static final Logger _logger =
LoggerFactory.getLogger(OnlineTicketServicesFactory.class);
LoggerFactory.getLogger(OnlineTicketServiceFactory.class);
public OnlineTicketServices getService(
public OnlineTicketService getService(
int persistence,
JdbcTemplate jdbcTemplate,
RedisConnectionFactory redisConnFactory){
OnlineTicketServices onlineTicketServices = null;
OnlineTicketService onlineTicketServices = null;
if (persistence == ConstsPersistence.INMEMORY) {
onlineTicketServices = new InMemoryOnlineTicketServices();
onlineTicketServices = new InMemoryOnlineTicketService();
_logger.debug("InMemoryOnlineTicketServices");
} else if (persistence == ConstsPersistence.JDBC) {
_logger.debug("OnlineTicketServices not support ");
} else if (persistence == ConstsPersistence.REDIS) {
onlineTicketServices = new RedisOnlineTicketServices(redisConnFactory);
onlineTicketServices = new RedisOnlineTicketService(redisConnFactory);
_logger.debug("RedisOnlineTicketServices");
}
@@ -26,8 +26,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RedisOnlineTicketServices implements OnlineTicketServices {
private static final Logger _logger = LoggerFactory.getLogger(RedisOnlineTicketServices.class);
public class RedisOnlineTicketService implements OnlineTicketService {
private static final Logger _logger = LoggerFactory.getLogger(RedisOnlineTicketService.class);
protected int serviceTicketValiditySeconds = 60 * 30; //default 30 minutes.
@@ -37,7 +37,7 @@ public class RedisOnlineTicketServices implements OnlineTicketServices {
/**
* @param connectionFactory
*/
public RedisOnlineTicketServices(RedisConnectionFactory connectionFactory) {
public RedisOnlineTicketService(RedisConnectionFactory connectionFactory) {
super();
this.connectionFactory = connectionFactory;
}
@@ -45,7 +45,7 @@ public class RedisOnlineTicketServices implements OnlineTicketServices {
/**
*
*/
public RedisOnlineTicketServices() {
public RedisOnlineTicketService() {
}
@@ -20,12 +20,14 @@ package org.maxkey.autoconfigure;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.RealmAuthenticationProvider;
import org.maxkey.authn.SavedRequestAwareAuthenticationSuccessHandler;
import org.maxkey.authn.online.OnlineTicketServices;
import org.maxkey.authn.online.OnlineTicketServicesFactory;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.online.OnlineTicketServiceFactory;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
import org.maxkey.authn.support.rememberme.RemeberMeServiceFactory;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.configuration.AuthJwkConfig;
import org.maxkey.constants.ConstsPersistence;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.password.onetimepwd.OtpAuthnService;
@@ -45,6 +47,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import com.nimbusds.jose.JOSEException;
@Configuration
public class AuthenticationAutoConfiguration implements InitializingBean {
@@ -65,7 +69,7 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
AbstractOtpAuthn tfaOtpAuthn,
OtpAuthnService otpAuthnService,
AbstractRemeberMeService remeberMeService,
OnlineTicketServices onlineTicketServices
OnlineTicketService onlineTicketServices
) {
_logger.debug("init authentication Provider .");
@@ -80,6 +84,12 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
}
@Bean(name = "authJwtService")
public AuthJwtService authJwtService(AuthJwkConfig authJwkConfig) throws JOSEException {
AuthJwtService authJwtService = new AuthJwtService(authJwkConfig);
return authJwtService;
}
@Bean(name = "otpAuthnService")
public OtpAuthnService otpAuthnService(
@Value("${maxkey.server.persistence}") int persistence,
@@ -127,18 +137,18 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
return new RemeberMeServiceFactory().getService(persistence, jdbcTemplate, redisConnFactory);
}
@Bean(name = "onlineTicketServices")
public OnlineTicketServices onlineTicketServices(
@Bean(name = "onlineTicketService")
public OnlineTicketService onlineTicketService(
@Value("${maxkey.server.persistence}") int persistence,
JdbcTemplate jdbcTemplate,
RedisConnectionFactory redisConnFactory,
@Value("${server.servlet.session.timeout:1800}") int timeout
) {
OnlineTicketServices onlineTicketServices =
new OnlineTicketServicesFactory().getService(persistence, jdbcTemplate, redisConnFactory);
onlineTicketServices.setValiditySeconds(timeout);
OnlineTicketService onlineTicketService =
new OnlineTicketServiceFactory().getService(persistence, jdbcTemplate, redisConnFactory);
onlineTicketService.setValiditySeconds(timeout);
_logger.trace("onlineTicket timeout " + timeout);
return onlineTicketServices;
return onlineTicketService;
}
@Override