Bläddra i källkod

add maxkey-authentication-provider-mgt

shimingxy 1 år sedan
förälder
incheckning
5b031b9746
22 ändrade filer med 1972 tillägg och 6 borttagningar
  1. 19 0
      maxkey-authentications/maxkey-authentication-provider-mgt/build.gradle
  2. 3 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/META-INF/MANIFEST.MF
  3. 262 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/AbstractAuthenticationProvider.java
  4. 58 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/AuthenticationProviderFactory.java
  5. 150 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/MobileAuthenticationProvider.java
  6. 138 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/NormalAuthenticationProvider.java
  7. 85 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/TrustedAuthenticationProvider.java
  8. 229 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/AbstractAuthenticationRealm.java
  9. 30 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/IAuthenticationServer.java
  10. 146 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/jdbc/JdbcAuthenticationRealm.java
  11. 88 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/ActiveDirectoryServer.java
  12. 94 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealm.java
  13. 93 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealmService.java
  14. 109 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/StandardLdapServer.java
  15. 119 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/support/jwt/HttpJwtEntryPoint.java
  16. 135 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/support/jwt/JwtLoginService.java
  17. 117 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/autoconfigure/AuthnProviderAutoConfiguration.java
  18. 89 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/autoconfigure/JwtAuthnAutoConfiguration.java
  19. 2 0
      maxkey-authentications/maxkey-authentication-provider-mgt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  20. 1 1
      maxkey-webs/maxkey-web-mgt/build.gradle
  21. 4 5
      maxkey-webs/maxkey-web-mgt/src/main/java/org/dromara/maxkey/web/contorller/LoginEntryPoint.java
  22. 1 0
      settings.gradle

+ 19 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/build.gradle

@@ -0,0 +1,19 @@
+
+description = "maxkey-authentication-provider-mgt"
+
+
+dependencies {
+	//local jars
+	implementation fileTree(dir: '../maxkey-lib/', include: '*/*.jar')
+	
+	implementation project(":maxkey-common")
+	implementation project(":maxkey-core")
+	implementation project(":maxkey-persistence")
+	
+	implementation project(":maxkey-starter:maxkey-starter-ip2location")
+	implementation project(":maxkey-starter:maxkey-starter-otp")
+	implementation project(":maxkey-starter:maxkey-starter-sms")
+	
+	implementation project(":maxkey-authentications:maxkey-authentication-core")
+   
+}

+ 3 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/META-INF/MANIFEST.MF

@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

+ 262 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/AbstractAuthenticationProvider.java

@@ -0,0 +1,262 @@
+/*
+ * 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.dromara.maxkey.authn.provider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.SignPrincipal;
+import org.dromara.maxkey.authn.jwt.AuthTokenService;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.web.AuthorizationUtils;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.constants.ConstsStatus;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.password.onetimepwd.AbstractOtpAuthn;
+import org.dromara.maxkey.password.onetimepwd.MailOtpAuthnService;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+/**
+ * login Authentication abstract class.
+ *
+ * @author Crystal.Sea
+ *
+ */
+public abstract class AbstractAuthenticationProvider {
+    private static final Logger _logger =
+            LoggerFactory.getLogger(AbstractAuthenticationProvider.class);
+
+    public static String PROVIDER_SUFFIX = "AuthenticationProvider";
+
+    public class AuthType{
+    	public static final  String NORMAL 	= "normal";
+    	public static final  String TFA 		= "tfa";
+    	public static final  String MOBILE 	= "mobile";
+    	public static final  String TRUSTED 	= "trusted";
+        /**
+         * 扫描认证
+         */
+        public static final  String SCAN_CODE 	= "scancode";
+
+        /**
+         * 手机端APP
+         */
+        public static final  String APP 		= "app";
+    }
+
+    protected ApplicationConfig applicationConfig;
+
+    protected AbstractAuthenticationRealm authenticationRealm;
+
+    protected AbstractOtpAuthn tfaOtpAuthn;
+
+    protected MailOtpAuthnService otpAuthnService;
+
+    protected SessionManager sessionManager;
+
+    protected AuthTokenService authTokenService;
+
+    public static  ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>();
+
+    static {
+        grantedAdministratorsAuthoritys.add(new SimpleGrantedAuthority("ROLE_ADMINISTRATORS"));
+    }
+
+    public abstract String getProviderName();
+
+    public abstract Authentication doAuthenticate(LoginCredential authentication);
+
+    @SuppressWarnings("rawtypes")
+    public boolean supports(Class authentication) {
+        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
+    }
+
+    public Authentication authenticate(LoginCredential authentication){
+    	return null;
+    }
+
+    public Authentication authenticate(LoginCredential authentication,boolean trusted) {
+    	return null;
+    }
+
+    /**
+     * createOnlineSession
+     * @param credential
+     * @param userInfo
+     * @return
+     */
+    public UsernamePasswordAuthenticationToken createOnlineTicket(LoginCredential credential,UserInfo userInfo) {
+        //create session
+        Session session = new Session();
+
+        //set session with principal
+        SignPrincipal principal = new SignPrincipal(userInfo,session);
+
+        List<GrantedAuthority> grantedAuthoritys = authenticationRealm.grantAuthority(userInfo);
+        principal.setAuthenticated(true);
+
+        for(GrantedAuthority administratorsAuthority : grantedAdministratorsAuthoritys) {
+            if(grantedAuthoritys.contains(administratorsAuthority)) {
+            	principal.setRoleAdministrators(true);
+                _logger.trace("ROLE ADMINISTRATORS Authentication .");
+            }
+        }
+        _logger.debug("Granted Authority {}" , grantedAuthoritys);
+
+        principal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys));
+
+        UsernamePasswordAuthenticationToken authenticationToken =
+                new UsernamePasswordAuthenticationToken(
+                		principal,
+                        "PASSWORD",
+                        grantedAuthoritys
+                );
+
+        authenticationToken.setDetails(
+                new WebAuthenticationDetails(WebContext.getRequest()));
+
+        /*
+         *  put Authentication to current session context
+         */
+        session.setAuthentication(authenticationToken);
+
+        //create session
+        this.sessionManager.create(session.getId(), session);
+
+        //set Authentication to http session
+        AuthorizationUtils.setAuthentication(authenticationToken);
+
+        return authenticationToken;
+    }
+
+    /**
+     * login user by j_username and j_cname first query user by j_cname if first
+     * step userinfo is null,query user from system.
+     *
+     * @param username String
+     * @param password String
+     * @return
+     */
+    public UserInfo loadUserInfo(String username, String password) {
+        UserInfo userInfo = authenticationRealm.loadUserInfo(username, password);
+
+        if (userInfo != null) {
+            if (userInfo.getUserType() == "SYSTEM") {
+                _logger.debug("SYSTEM User Login. ");
+            } else {
+                _logger.debug("User Login. ");
+            }
+
+        }
+
+        return userInfo;
+    }
+
+    /**
+     * check input password empty.
+     *
+     * @param password String
+     * @return
+     */
+    protected boolean emptyPasswordValid(String password) {
+        if (null == password || "".equals(password)) {
+            throw new BadCredentialsException(WebContext.getI18nValue("login.error.password.null"));
+        }
+        return true;
+    }
+
+    /**
+     * check input username or password empty.
+     *
+     * @param email String
+     * @return
+     */
+    protected boolean emptyEmailValid(String email) {
+        if (null == email || "".equals(email)) {
+            throw new BadCredentialsException("login.error.email.null");
+        }
+        return true;
+    }
+
+    /**
+     * check input username empty.
+     *
+     * @param username String
+     * @return
+     */
+    protected boolean emptyUsernameValid(String username) {
+        if (null == username || "".equals(username)) {
+            throw new BadCredentialsException(WebContext.getI18nValue("login.error.username.null"));
+        }
+        return true;
+    }
+
+    protected boolean isUserExist(LoginCredential loginCredential , UserInfo userInfo) {
+        if (null == userInfo) {
+            String i18nMessage = WebContext.getI18nValue("login.error.username");
+            _logger.debug("login user  {} not in this System , message {} ." ,loginCredential.getUsername(), i18nMessage);
+            UserInfo loginUser = new UserInfo(loginCredential.getUsername());
+            loginUser.setId(loginUser.generateId());
+            loginUser.setUsername(loginCredential.getUsername());
+            loginUser.setDisplayName("not exist");
+            loginUser.setLoginCount(0);
+            authenticationRealm.insertLoginHistory(
+            			loginUser,
+            			ConstsLoginType.LOCAL,
+            			"",
+            			i18nMessage,
+            			WebConstants.LOGIN_RESULT.USER_NOT_EXIST);
+            throw new BadCredentialsException(i18nMessage);
+        }
+        return true;
+    }
+
+    protected boolean statusValid(LoginCredential loginCredential , UserInfo userInfo) {
+    	if(userInfo.getIsLocked()==ConstsStatus.LOCK) {
+    		authenticationRealm.insertLoginHistory(
+    				userInfo,
+                    loginCredential.getAuthType(),
+                    loginCredential.getProvider(),
+                    loginCredential.getCode(),
+                    WebConstants.LOGIN_RESULT.USER_LOCKED
+                );
+    	}else if(userInfo.getStatus()!=ConstsStatus.ACTIVE) {
+    		authenticationRealm.insertLoginHistory(
+    				userInfo,
+                    loginCredential.getAuthType(),
+                    loginCredential.getProvider(),
+                    loginCredential.getCode(),
+                    WebConstants.LOGIN_RESULT.USER_INACTIVE
+                );
+    	}
+        return true;
+    }
+
+}

+ 58 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/AuthenticationProviderFactory.java

@@ -0,0 +1,58 @@
+/*
+ * 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.dromara.maxkey.authn.provider;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.springframework.security.core.Authentication;
+
+public class AuthenticationProviderFactory extends AbstractAuthenticationProvider {
+
+    private  static ConcurrentHashMap<String,AbstractAuthenticationProvider> providers = new ConcurrentHashMap<>();
+    
+    @Override
+    public Authentication authenticate(LoginCredential authentication){
+    	if(authentication.getAuthType().equalsIgnoreCase("trusted")) {
+    		//risk remove
+    		return null;
+    	}
+    	AbstractAuthenticationProvider provider = providers.get(authentication.getAuthType() + PROVIDER_SUFFIX);
+    	
+    	return provider == null ? null : provider.doAuthenticate(authentication);
+    }
+    
+    @Override
+    public Authentication authenticate(LoginCredential authentication,boolean trusted){
+    	AbstractAuthenticationProvider provider = providers.get(AuthType.TRUSTED + PROVIDER_SUFFIX);
+    	return provider.doAuthenticate(authentication);
+    }
+    
+    public void addAuthenticationProvider(AbstractAuthenticationProvider provider) {
+    	providers.put(provider.getProviderName(), provider);
+    }
+
+	@Override
+	public String getProviderName() {
+		return "AuthenticationProviderFactory";
+	}
+
+	@Override
+	public Authentication doAuthenticate(LoginCredential authentication) {
+		//AuthenticationProvider Factory do nothing 
+		return null;
+	}
+}

+ 150 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/MobileAuthenticationProvider.java

@@ -0,0 +1,150 @@
+/*
+ * 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.dromara.maxkey.authn.provider.impl;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.password.onetimepwd.AbstractOtpAuthn;
+import org.dromara.maxkey.password.sms.SmsOtpAuthnService;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+
+/**
+ * Mobile Authentication provider.
+ * @author Crystal.Sea
+ *
+ */
+public class MobileAuthenticationProvider extends AbstractAuthenticationProvider {
+
+    private static final Logger _logger =
+            LoggerFactory.getLogger(MobileAuthenticationProvider.class);
+
+    SmsOtpAuthnService smsOtpAuthnService;
+    
+    @Override
+    public String getProviderName() {
+        return "mobile" + PROVIDER_SUFFIX;
+    }
+
+
+    public MobileAuthenticationProvider() {
+        super();
+    }
+
+
+    public MobileAuthenticationProvider(
+            AbstractAuthenticationRealm authenticationRealm,
+            ApplicationConfig applicationConfig,
+            SmsOtpAuthnService smsOtpAuthnService,
+            SessionManager sessionManager) {
+        this.authenticationRealm = authenticationRealm;
+        this.applicationConfig = applicationConfig;
+        this.smsOtpAuthnService = smsOtpAuthnService;
+        this.sessionManager = sessionManager;
+    }
+
+    @Override
+    public Authentication doAuthenticate(LoginCredential loginCredential) {
+        UsernamePasswordAuthenticationToken authenticationToken = null;
+        _logger.debug("Trying to authenticate user '{}' via {}",
+                loginCredential.getPrincipal(), getProviderName());
+        try {
+
+            //如果是验证码登录,设置mobile为username
+            loginCredential.setUsername(loginCredential.getMobile());
+            //设置密码为验证码
+            loginCredential.setPassword(loginCredential.getOtpCaptcha());
+
+            _logger.debug("authentication " + loginCredential);
+
+            emptyPasswordValid(loginCredential.getPassword());
+
+            emptyUsernameValid(loginCredential.getUsername());
+
+            UserInfo userInfo =  loadUserInfo(loginCredential.getUsername(),loginCredential.getPassword());
+
+            isUserExist(loginCredential , userInfo);
+            
+            statusValid(loginCredential , userInfo);
+
+            mobileCaptchaValid(loginCredential.getPassword(),userInfo);
+
+            //apply PasswordSetType and resetBadPasswordCount
+            authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
+
+            authenticationToken = createOnlineTicket(loginCredential,userInfo);
+            // user authenticated
+            _logger.debug("'{}' authenticated successfully by {}.",
+                    loginCredential.getPrincipal(), getProviderName());
+
+            authenticationRealm.insertLoginHistory(userInfo,
+                    ConstsLoginType.LOCAL,
+                    "",
+                    "xe00000004",
+                    WebConstants.LOGIN_RESULT.SUCCESS);
+        } catch (AuthenticationException e) {
+            _logger.error("Failed to authenticate user {} via {}: {}",
+                    new Object[] {  loginCredential.getPrincipal(),
+                            getProviderName(),
+                            e.getMessage() });
+            WebContext.setAttribute(
+                    WebConstants.LOGIN_ERROR_SESSION_MESSAGE, e.getMessage());
+        } catch (Exception e) {
+            _logger.error("Login error Unexpected exception in {} authentication:\n{}" ,
+                    getProviderName(), e.getMessage());
+        }
+
+        return  authenticationToken;
+    }
+
+
+    /**
+     * mobile validate.
+     *
+     * @param otpCaptcha String
+     * @param authType   String
+     * @param userInfo   UserInfo
+     */
+    protected void mobileCaptchaValid(String password, UserInfo userInfo) {
+        // for mobile password
+        if (applicationConfig.getLoginConfig().isMfa()) {
+            UserInfo validUserInfo = new UserInfo();
+            validUserInfo.setUsername(userInfo.getUsername());
+            validUserInfo.setId(userInfo.getId());
+            AbstractOtpAuthn smsOtpAuthn = smsOtpAuthnService.getByInstId(userInfo.getInstId());
+            if (password == null || !smsOtpAuthn.validate(validUserInfo, password)) {
+                String message = WebContext.getI18nValue("login.error.captcha");
+                _logger.debug("login captcha valid error.");
+                throw new BadCredentialsException(message);
+            }
+        }
+    }
+
+}

+ 138 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/NormalAuthenticationProvider.java

@@ -0,0 +1,138 @@
+/*
+ * 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.dromara.maxkey.authn.provider.impl;
+
+import java.text.ParseException;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.jwt.AuthTokenService;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * database Authentication provider.
+ * @author Crystal.Sea
+ *
+ */
+public class NormalAuthenticationProvider extends AbstractAuthenticationProvider {
+    private static final Logger _logger = LoggerFactory.getLogger(NormalAuthenticationProvider.class);
+
+    @Override
+    public String getProviderName() {
+        return "normal" + PROVIDER_SUFFIX;
+    }
+    
+
+    public NormalAuthenticationProvider() {
+		super();
+	}
+
+    public NormalAuthenticationProvider(
+    		AbstractAuthenticationRealm authenticationRealm,
+    		ApplicationConfig applicationConfig,
+    	    SessionManager sessionManager,
+    	    AuthTokenService authTokenService) {
+		this.authenticationRealm = authenticationRealm;
+		this.applicationConfig = applicationConfig;
+		this.sessionManager = sessionManager;
+		this.authTokenService = authTokenService;
+	}
+
+    @Override
+	public Authentication doAuthenticate(LoginCredential loginCredential) {
+		UsernamePasswordAuthenticationToken authenticationToken = null;
+		_logger.debug("Trying to authenticate user '{}' via {}", 
+                loginCredential.getPrincipal(), getProviderName());
+        try {
+        	
+	        _logger.debug("authentication {}" , loginCredential);
+	        
+	        if(this.applicationConfig.getLoginConfig().isCaptcha()) {
+	        	captchaValid(loginCredential.getState(),loginCredential.getCaptcha());
+	        }
+	
+	        emptyPasswordValid(loginCredential.getPassword());
+	
+	        emptyUsernameValid(loginCredential.getUsername());
+	
+	        UserInfo userInfo =  loadUserInfo(loginCredential.getUsername(),loginCredential.getPassword());
+	
+	        isUserExist(loginCredential , userInfo);
+	        
+	        //Validate PasswordPolicy
+	        authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo);
+	        
+	        statusValid(loginCredential , userInfo);
+	        
+	        //Match password 
+	        authenticationRealm.passwordMatches(userInfo, loginCredential.getPassword());
+
+	        //apply PasswordSetType and resetBadPasswordCount
+	        authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
+	        
+	        authenticationToken = createOnlineTicket(loginCredential,userInfo);
+	        // user authenticated
+	        _logger.debug("'{}' authenticated successfully by {}.", 
+	        		loginCredential.getPrincipal(), getProviderName());
+	        
+	        authenticationRealm.insertLoginHistory(userInfo, 
+							        				ConstsLoginType.LOCAL, 
+									                "", 
+									                "xe00000004", 
+									                WebConstants.LOGIN_RESULT.SUCCESS);
+        } catch (AuthenticationException e) {
+            _logger.error("Failed to authenticate user {} via {}: {}",
+                    				loginCredential.getPrincipal(),
+                                    getProviderName(),
+                                    e.getMessage() );
+            WebContext.setAttribute(
+                    WebConstants.LOGIN_ERROR_SESSION_MESSAGE, e.getMessage());
+        } catch (Exception e) {
+            _logger.error("Login error Unexpected exception in {} authentication:\n{}" ,
+                            getProviderName(), e.getMessage());
+        }
+       
+        return  authenticationToken;
+    }
+    
+    /**
+     * captcha validate .
+     * 
+     * @param authType String
+     * @param captcha String
+     * @throws ParseException 
+     */
+    protected void captchaValid(String state ,String captcha) {
+        // for basic
+    	if(!authTokenService.validateCaptcha(state,captcha)) {
+    		throw new BadCredentialsException(WebContext.getI18nValue("login.error.captcha"));
+    	}        
+    }
+}

+ 85 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/provider/impl/TrustedAuthenticationProvider.java

@@ -0,0 +1,85 @@
+/*
+ * 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.dromara.maxkey.authn.provider.impl;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+
+/**
+ * Trusted Authentication provider.
+ * @author Crystal.Sea
+ *
+ */
+public class TrustedAuthenticationProvider extends AbstractAuthenticationProvider {
+    private static final Logger _logger = LoggerFactory.getLogger(TrustedAuthenticationProvider.class);
+
+    @Override
+    public String getProviderName() {
+        return "trusted" + PROVIDER_SUFFIX;
+    }
+    
+    public TrustedAuthenticationProvider() {
+		super();
+	}
+
+    public TrustedAuthenticationProvider(
+    		AbstractAuthenticationRealm authenticationRealm,
+    		ApplicationConfig applicationConfig,
+    	    SessionManager sessionManager) {
+		this.authenticationRealm = authenticationRealm;
+		this.applicationConfig = applicationConfig;
+		this.sessionManager = sessionManager;
+	}
+
+    @Override
+	public Authentication doAuthenticate(LoginCredential loginCredential) {
+        UserInfo loadeduserInfo = loadUserInfo(loginCredential.getUsername(), "");
+        statusValid(loginCredential , loadeduserInfo);
+        if (loadeduserInfo != null) {
+            //Validate PasswordPolicy
+            authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(loadeduserInfo);
+            //apply PasswordSetType and resetBadPasswordCount
+            authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(loadeduserInfo);
+            Authentication authentication = createOnlineTicket(loginCredential,loadeduserInfo);
+            
+            authenticationRealm.insertLoginHistory( loadeduserInfo, 
+                                                    loginCredential.getAuthType(), 
+                                                    loginCredential.getProvider(), 
+                                                    loginCredential.getCode(), 
+                                                    loginCredential.getMessage()
+                                                );
+            
+            return authentication;
+        }else {
+            String i18nMessage = WebContext.getI18nValue("login.error.username");
+            _logger.debug("login user {} not in this System . {}" , 
+                            loginCredential.getUsername(),i18nMessage);
+            throw new BadCredentialsException(WebContext.getI18nValue("login.error.username"));
+        }
+    }
+  
+}

+ 229 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/AbstractAuthenticationRealm.java

@@ -0,0 +1,229 @@
+/*
+ * 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.dromara.maxkey.authn.realm;
+
+import java.util.Date;
+import java.util.List;
+
+import org.dromara.maxkey.authn.SignPrincipal;
+import org.dromara.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
+import org.dromara.maxkey.entity.history.HistoryLogin;
+import org.dromara.maxkey.entity.idm.Groups;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.ip2location.IpLocationParser;
+import org.dromara.maxkey.ip2location.Region;
+import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;
+import org.dromara.maxkey.persistence.repository.LoginRepository;
+import org.dromara.maxkey.persistence.repository.PasswordPolicyValidator;
+import org.dromara.maxkey.persistence.service.UserInfoService;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+/**
+ * AbstractAuthenticationRealm.
+ * @author Crystal.Sea
+ *
+ */
+public abstract class AbstractAuthenticationRealm {
+    private static final Logger _logger = LoggerFactory.getLogger(AbstractAuthenticationRealm.class);
+
+    protected JdbcTemplate jdbcTemplate;
+    
+    protected PasswordPolicyValidator passwordPolicyValidator;
+    
+    protected LoginRepository loginRepository;
+
+    protected LoginHistoryRepository loginHistoryRepository;
+    
+    protected UserInfoService userInfoService;
+    
+    protected LdapAuthenticationRealmService ldapAuthenticationRealmService;
+    
+    protected IpLocationParser ipLocationParser;
+   
+
+    /**
+     * 
+     */
+    public AbstractAuthenticationRealm() {
+
+    }
+
+    public AbstractAuthenticationRealm(JdbcTemplate jdbcTemplate) {
+        this.jdbcTemplate = jdbcTemplate;
+    }
+
+    public PasswordPolicyValidator getPasswordPolicyValidator() {
+        return passwordPolicyValidator;
+    }
+
+    public LoginRepository getLoginRepository() {
+        return loginRepository;
+    }
+
+    public UserInfo loadUserInfo(String username, String password) {
+        return loginRepository.find(username, password);
+    }
+
+    public abstract boolean passwordMatches(UserInfo userInfo, String password);
+    
+    public List<Groups> queryGroups(UserInfo userInfo) {
+       return loginRepository.queryGroups(userInfo);
+    }
+
+    /**
+     * grant Authority by userinfo
+     * 
+     * @param userInfo
+     * @return ArrayList<GrantedAuthority>
+     */
+    public List<GrantedAuthority> grantAuthority(UserInfo userInfo) {
+        return loginRepository.grantAuthority(userInfo);
+    }
+    
+    /**
+     * grant Authority by grantedAuthoritys
+     * 
+     * @param grantedAuthoritys
+     * @return ArrayList<GrantedAuthority Apps>
+     */
+    public List<GrantedAuthority> queryAuthorizedApps(List<GrantedAuthority> grantedAuthoritys) {
+        return loginRepository.queryAuthorizedApps(grantedAuthoritys);
+    }
+
+    /**
+     * login log write to log db
+     * 
+     * @param uid
+     * @param j_username
+     * @param type
+     * @param code
+     * @param message
+     */
+    public boolean insertLoginHistory(UserInfo userInfo, String type, String provider, String code, String message) {
+        HistoryLogin historyLogin = new HistoryLogin();
+        historyLogin.setSessionId(WebContext.genId());
+        historyLogin.setSessionStatus(7);
+        Authentication  authentication  = (Authentication ) WebContext.getAttribute(WebConstants.AUTHENTICATION);
+        if(authentication != null 
+        		&& authentication.getPrincipal() instanceof SignPrincipal) {
+        	  historyLogin.setSessionStatus(1);
+              historyLogin.setSessionId(userInfo.getSessionId());
+        }
+        
+        _logger.debug("user session id is {} . ",historyLogin.getSessionId());
+        
+        userInfo.setLastLoginTime(new Date());
+        userInfo.setLastLoginIp(WebContext.getRequestIpAddress());
+        
+        Browser browser = resolveBrowser();
+        historyLogin.setBrowser(browser.getName());
+        historyLogin.setPlatform(browser.getPlatform());
+        historyLogin.setSourceIp(userInfo.getLastLoginIp());
+        historyLogin.setProvider(provider);
+        historyLogin.setCode(code);
+        historyLogin.setLoginType(type);
+        historyLogin.setMessage(message);
+        historyLogin.setUserId(userInfo.getId());
+        historyLogin.setUsername(userInfo.getUsername());
+        historyLogin.setDisplayName(userInfo.getDisplayName());
+        historyLogin.setInstId(userInfo.getInstId());
+        
+        Region ipRegion =ipLocationParser.region(userInfo.getLastLoginIp());
+        if(ipRegion != null) {
+        	historyLogin.setCountry(ipRegion.getCountry());
+        	historyLogin.setProvince(ipRegion.getProvince());
+        	historyLogin.setCity(ipRegion.getCity());
+        	historyLogin.setLocation(ipRegion.getAddr());
+        }
+        loginHistoryRepository.login(historyLogin);
+        
+        loginRepository.updateLastLogin(userInfo);
+
+        return true;
+    }
+    
+    public Browser  resolveBrowser() {
+        Browser browser =new Browser();
+        String userAgent = WebContext.getRequest().getHeader("User-Agent");
+        String[] arrayUserAgent = null;
+        if (userAgent.indexOf("MSIE") > 0) {
+            arrayUserAgent = userAgent.split(";");
+            browser.setName(arrayUserAgent[1].trim());
+            browser.setPlatform(arrayUserAgent[2].trim());
+        } else if (userAgent.indexOf("Trident") > 0) {
+            arrayUserAgent = userAgent.split(";");
+            browser.setName( "MSIE/" + arrayUserAgent[3].split("\\)")[0]);
+
+            browser.setPlatform( arrayUserAgent[0].split("\\(")[1]);
+        } else if (userAgent.indexOf("Chrome") > 0) {
+            arrayUserAgent = userAgent.split(" ");
+            // browser=arrayUserAgent[8].trim();
+            for (int i = 0; i < arrayUserAgent.length; i++) {
+                if (arrayUserAgent[i].contains("Chrome")) {
+                    browser.setName( arrayUserAgent[i].trim());
+                    browser.setName( browser.getName().substring(0, browser.getName().indexOf('.')));
+                }
+            }
+            browser.setPlatform( (arrayUserAgent[1].substring(1) + " " + arrayUserAgent[2] + " "
+                    + arrayUserAgent[3].substring(0, arrayUserAgent[3].length() - 1)).trim());
+        } else if (userAgent.indexOf("Firefox") > 0) {
+            arrayUserAgent = userAgent.split(" ");
+            for (int i = 0; i < arrayUserAgent.length; i++) {
+                if (arrayUserAgent[i].contains("Firefox")) {
+                    browser.setName( arrayUserAgent[i].trim());
+                    browser.setName(browser.getName().substring(0, browser.getName().indexOf('.')));
+                }
+            }
+            browser.setPlatform( (arrayUserAgent[1].substring(1) + " " + arrayUserAgent[2] + " "
+                    + arrayUserAgent[3].substring(0, arrayUserAgent[3].length() - 1)).trim());
+
+        }
+        
+        return browser;
+    }
+    
+    
+    public class Browser{
+        
+        private  String platform;
+        
+        private  String name;
+        
+        public String getPlatform() {
+            return platform;
+        }
+        public void setPlatform(String platform) {
+            this.platform = platform;
+        }
+        public String getName() {
+            return name;
+        }
+        public void setName(String browser) {
+            this.name = browser;
+        }
+        
+        
+    }
+    
+}

+ 30 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/IAuthenticationServer.java

@@ -0,0 +1,30 @@
+/*
+ * 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.dromara.maxkey.authn.realm;
+
+/**
+ * IAuthenticationServer .
+ * @author Crystal.Sea
+ *
+ */
+public interface IAuthenticationServer {
+
+    public boolean authenticate(String username, String password);
+    
+    public boolean isMapping();
+}

+ 146 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/jdbc/JdbcAuthenticationRealm.java

@@ -0,0 +1,146 @@
+/*
+ * 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.dromara.maxkey.authn.realm.jdbc;
+
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.realm.ldap.LdapAuthenticationRealm;
+import org.dromara.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.constants.ConstsStatus;
+import org.dromara.maxkey.entity.ChangePassword;
+import org.dromara.maxkey.entity.cnf.CnfPasswordPolicy;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.ip2location.IpLocationParser;
+import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;
+import org.dromara.maxkey.persistence.repository.LoginRepository;
+import org.dromara.maxkey.persistence.repository.PasswordPolicyValidator;
+import org.dromara.maxkey.persistence.service.UserInfoService;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+/**
+ * JdbcAuthenticationRealm.
+ * @author Crystal.Sea
+ *
+ */
+public class JdbcAuthenticationRealm extends AbstractAuthenticationRealm {
+    private static final Logger  _logger = LoggerFactory.getLogger(JdbcAuthenticationRealm.class);
+
+    protected PasswordEncoder passwordEncoder;
+    
+    public JdbcAuthenticationRealm() {
+        _logger.debug("init . ");
+    }
+
+    public JdbcAuthenticationRealm(JdbcTemplate jdbcTemplate) {
+        this.jdbcTemplate = jdbcTemplate;
+    }
+    
+    public JdbcAuthenticationRealm(
+    		PasswordEncoder passwordEncoder,
+    		PasswordPolicyValidator passwordPolicyValidator,
+    		LoginRepository loginRepository,
+    		LoginHistoryRepository loginHistoryRepository,
+    		UserInfoService userInfoService,
+    		IpLocationParser ipLocationParser,
+    	    JdbcTemplate jdbcTemplate) {
+    	
+    	this.passwordEncoder =passwordEncoder;
+    	this.passwordPolicyValidator=passwordPolicyValidator;
+    	this.loginRepository = loginRepository;
+    	this.loginHistoryRepository = loginHistoryRepository;
+    	this.userInfoService = userInfoService;
+    	this.ipLocationParser = ipLocationParser;
+        this.jdbcTemplate = jdbcTemplate;
+    }
+  
+    public JdbcAuthenticationRealm(
+    		PasswordEncoder passwordEncoder,
+    		PasswordPolicyValidator passwordPolicyValidator,
+    		LoginRepository loginRepository,
+    		LoginHistoryRepository loginHistoryRepository,
+    		UserInfoService userInfoService,
+    		IpLocationParser ipLocationParser,
+    	    JdbcTemplate jdbcTemplate,
+    	    LdapAuthenticationRealmService ldapAuthenticationRealmService) {
+		this.passwordEncoder = passwordEncoder;
+		this.passwordPolicyValidator = passwordPolicyValidator;
+		this.loginRepository = loginRepository;
+		this.loginHistoryRepository = loginHistoryRepository;
+		this.userInfoService = userInfoService;
+		this.ipLocationParser = ipLocationParser;
+		this.jdbcTemplate = jdbcTemplate;
+		this.ldapAuthenticationRealmService = ldapAuthenticationRealmService;
+    }
+    
+    /**
+     * passwordMatches.
+     */
+    @Override
+    public boolean passwordMatches(UserInfo userInfo, String password) {
+        boolean passwordMatches = false;
+        //jdbc password check
+        //_logger.trace("password : " 
+        //        + PasswordReciprocal.getInstance().rawPassword(userInfo.getUsername(), password));
+        passwordMatches = passwordEncoder.matches(password,userInfo.getPassword());
+        
+        if(ldapAuthenticationRealmService != null) {
+        	//passwordMatches == false and ldapSupport ==true
+        	//validate password with LDAP
+	        try {
+	        	LdapAuthenticationRealm ldapRealm = ldapAuthenticationRealmService.getByInstId(userInfo.getInstId());
+	        	if(!passwordMatches && ldapRealm != null 
+		        		&& ldapRealm.isLdapSupport() 
+		        		&& userInfo.getIsLocked() == ConstsStatus.ACTIVE) {
+		            passwordMatches = ldapRealm.passwordMatches(userInfo, password);
+		            if(passwordMatches) {
+		                //write password to database Realm
+		            	ChangePassword changePassword = new ChangePassword(userInfo);
+		                changePassword.setPassword(password);
+		                userInfoService.changePassword(changePassword, false);
+		            }
+		        }
+	        }catch(Exception e) {
+	        	_logger.debug("passwordvalid Exception : {}" , e);
+	        }
+        }
+        _logger.debug("passwordvalid : {}" , passwordMatches);
+        if (!passwordMatches) {
+            passwordPolicyValidator.plusBadPasswordCount(userInfo);
+            insertLoginHistory(userInfo, ConstsLoginType.LOCAL, "", "xe00000004", WebConstants.LOGIN_RESULT.PASSWORD_ERROE);
+            CnfPasswordPolicy passwordPolicy = passwordPolicyValidator.getPasswordPolicyRepository().getPasswordPolicy();
+            if(userInfo.getBadPasswordCount()>=(passwordPolicy.getAttempts()/2)) {
+                throw new BadCredentialsException(
+                        WebContext.getI18nValue("login.error.password.attempts",
+                                new Object[]{
+                                        userInfo.getBadPasswordCount() + 1,
+                                        passwordPolicy.getAttempts(),
+                                        passwordPolicy.getDuration()}));
+            }else {
+                throw new BadCredentialsException(WebContext.getI18nValue("login.error.password"));
+            }
+        }
+        return passwordMatches;
+    }
+
+}

+ 88 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/ActiveDirectoryServer.java

@@ -0,0 +1,88 @@
+/*
+ * 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.dromara.maxkey.authn.realm.ldap;
+
+import org.dromara.maxkey.authn.realm.IAuthenticationServer;
+import org.dromara.maxkey.ldap.ActiveDirectoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Crystal.Sea
+ *
+ */
+public final class ActiveDirectoryServer implements IAuthenticationServer {
+	private static final  Logger _logger = LoggerFactory.getLogger(ActiveDirectoryServer.class);
+
+	ActiveDirectoryUtils activeDirectoryUtils;
+
+	String filter;
+	
+	boolean mapping;
+	
+	/* (non-Javadoc)
+	 * @see com.connsec.web.authentication.realm.IAuthenticationServer#authenticate(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public boolean authenticate(String username, String password) {
+		ActiveDirectoryUtils ldapPassWordValid = 
+    		        new ActiveDirectoryUtils(
+    		                activeDirectoryUtils.getProviderUrl(),
+    		                username, 
+    		                password,
+    		                activeDirectoryUtils.getDomain()
+    		         );
+		ldapPassWordValid.openConnection();
+		if(ldapPassWordValid.getCtx()!=null){
+			_logger.debug("Active Directory user " + username + "  is validate .");
+			ldapPassWordValid.close();
+			return true;
+		}
+		
+		ldapPassWordValid.close();
+		return false;
+	}
+
+	public ActiveDirectoryUtils getActiveDirectoryUtils() {
+		return activeDirectoryUtils;
+	}
+
+	public void setActiveDirectoryUtils(ActiveDirectoryUtils activeDirectoryUtils) {
+		this.activeDirectoryUtils = activeDirectoryUtils;
+	}
+
+	public String getFilter() {
+		return filter;
+	}
+
+	public void setFilter(String filter) {
+		this.filter = filter;
+	}
+
+	@Override
+	public boolean isMapping() {
+		return mapping;
+	}
+
+	public void setMapping(boolean mapping) {
+		this.mapping = mapping;
+	}
+}

+ 94 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealm.java

@@ -0,0 +1,94 @@
+/*
+ * 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.dromara.maxkey.authn.realm.ldap;
+
+import java.util.List;
+
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.realm.IAuthenticationServer;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+public class LdapAuthenticationRealm  extends AbstractAuthenticationRealm{
+	private static final  Logger _logger = LoggerFactory.getLogger(LdapAuthenticationRealm.class);
+	
+	@NotNull
+    @Size(min=1)
+    private List<IAuthenticationServer> ldapServers;
+	
+	private boolean ldapSupport;
+	
+	/**
+	 * 
+	 */
+	public LdapAuthenticationRealm() {
+		
+	}
+
+	public LdapAuthenticationRealm(boolean ldapSupport) {
+		this.ldapSupport = ldapSupport;
+	}
+	
+	/**
+	 * @param jdbcTemplate
+	 */
+	public LdapAuthenticationRealm(JdbcTemplate jdbcTemplate) {
+		super(jdbcTemplate);
+	}
+	
+	
+	@Override
+	public boolean passwordMatches(UserInfo userInfo, String password) {
+		 boolean isAuthenticated=false;
+		 for (final IAuthenticationServer ldapServer : this.ldapServers) {
+			 String username = userInfo.getUsername();
+			 if(ldapServer.isMapping()) {//if ldap Context accountMapping equals YES 
+				 username = userInfo.getWindowsAccount();
+			 }
+            _logger.debug("Attempting to authenticate {} at {}", username, ldapServer);
+            try {
+            	isAuthenticated = ldapServer.authenticate(username, password);
+            }catch(Exception e) {
+            	_logger.debug("Attempting Authenticated fail .");
+            }
+            if (isAuthenticated ) {
+            	return true;
+            }
+		 }
+		return false;
+	}
+
+	public void setLdapServers(List<IAuthenticationServer> ldapServers) {
+		this.ldapServers = ldapServers;
+	}
+
+	public boolean isLdapSupport() {
+		return ldapSupport;
+	}
+
+	public void setLdapSupport(boolean ldapSupport) {
+		this.ldapSupport = ldapSupport;
+	}
+
+
+}

+ 93 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealmService.java

@@ -0,0 +1,93 @@
+/*
+ * 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.dromara.maxkey.authn.realm.ldap;
+
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.dromara.maxkey.authn.realm.IAuthenticationServer;
+import org.dromara.maxkey.crypto.password.PasswordReciprocal;
+import org.dromara.maxkey.entity.cnf.CnfLdapContext;
+import org.dromara.maxkey.ldap.ActiveDirectoryUtils;
+import org.dromara.maxkey.ldap.LdapUtils;
+import org.dromara.maxkey.persistence.service.CnfLdapContextService;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+
+public class LdapAuthenticationRealmService {
+    protected static final Cache<String, LdapAuthenticationRealm> ldapRealmStore = 
+            Caffeine.newBuilder()
+                .expireAfterWrite(60, TimeUnit.MINUTES)
+                .build();
+    
+    CnfLdapContextService ldapContextService;
+    
+    
+    public LdapAuthenticationRealmService(CnfLdapContextService ldapContextService) {
+		this.ldapContextService = ldapContextService;
+	}
+
+	public LdapAuthenticationRealm getByInstId(String instId) {
+		LdapAuthenticationRealm authenticationRealm = ldapRealmStore.getIfPresent(instId);
+		if(authenticationRealm == null) {
+			List<CnfLdapContext> ldapContexts = 
+					ldapContextService.find("where instid = ? and status = 1 ", new Object[]{instId}, new int[]{Types.VARCHAR});
+			authenticationRealm = new LdapAuthenticationRealm(false);
+			if(ldapContexts != null && ldapContexts.size()>0) {
+				authenticationRealm.setLdapSupport(true);
+				List<IAuthenticationServer> ldapAuthenticationServers = new ArrayList<IAuthenticationServer>();
+				for(CnfLdapContext ldapContext : ldapContexts) { 
+					if(ldapContext.getProduct().equalsIgnoreCase("ActiveDirectory")) {
+						ActiveDirectoryServer ldapServer = new ActiveDirectoryServer();
+			            ActiveDirectoryUtils  ldapUtils  = new ActiveDirectoryUtils(
+			            								ldapContext.getProviderUrl(),
+			            								ldapContext.getPrincipal(),
+			            								PasswordReciprocal.getInstance().decoder(
+			            										ldapContext.getCredentials()),
+			            								ldapContext.getMsadDomain());
+			            ldapServer.setActiveDirectoryUtils(ldapUtils);
+			            if(ldapContext.getAccountMapping().equalsIgnoreCase("YES")) {
+			            	ldapServer.setMapping(true);
+			            }
+			            ldapAuthenticationServers.add(ldapServer);
+						
+					}else {
+						StandardLdapServer standardLdapServer=new StandardLdapServer();
+						LdapUtils ldapUtils = new LdapUtils(
+													ldapContext.getProviderUrl(),
+													ldapContext.getPrincipal(),
+													PasswordReciprocal.getInstance().decoder(
+		            										ldapContext.getCredentials()),
+													ldapContext.getBasedn());
+						standardLdapServer.setLdapUtils(ldapUtils);
+						standardLdapServer.setFilterAttribute(ldapContext.getFilters());
+						if(ldapContext.getAccountMapping().equalsIgnoreCase("YES")) {
+							standardLdapServer.setMapping(true);
+			            }
+						ldapAuthenticationServers.add(standardLdapServer);
+					}
+				}
+				authenticationRealm.setLdapServers(ldapAuthenticationServers);
+			}
+			ldapRealmStore.put(instId, authenticationRealm);
+		}
+    	return authenticationRealm;
+    	
+    }
+}

+ 109 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/realm/ldap/StandardLdapServer.java

@@ -0,0 +1,109 @@
+/*
+ * 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.dromara.maxkey.authn.realm.ldap;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.dromara.maxkey.authn.realm.IAuthenticationServer;
+import org.dromara.maxkey.ldap.LdapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Crystal.Sea
+ *
+ */
+public final class StandardLdapServer implements IAuthenticationServer {
+	private static final  Logger _logger = LoggerFactory.getLogger(StandardLdapServer.class);
+	
+	LdapUtils ldapUtils;
+	
+	String filterAttribute;
+	
+	boolean mapping;
+	
+	/* (non-Javadoc)
+	 * @see com.connsec.web.authentication.realm.IAuthenticationServer#authenticate(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public boolean authenticate(String username, String password) {
+		String queryFilter = String.format(filterAttribute, username);
+		_logger.info(" filter : " + queryFilter);
+		String dn="";
+		SearchControls constraints = new SearchControls();
+		constraints.setSearchScope(ldapUtils.getSearchScope());
+		try {
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), queryFilter, constraints);
+			
+			if (results == null || !results.hasMore()) {
+				_logger.error("Ldap user "+username +" not found . ");
+				return false;
+			}else{
+				while (results != null && results.hasMore()) {
+					SearchResult sr = (SearchResult) results.next();
+					//String rdn = sr.getName();
+					dn = sr.getNameInNamespace();
+					_logger.debug("Directory user dn is "+dn+" .");
+				}
+			}
+		} catch (NamingException e) {
+			_logger.error("query throw NamingException:" + e.getMessage());
+		} finally {
+			//ldapUtils.close();
+		}
+		
+		LdapUtils ldapPassWordValid=new LdapUtils(ldapUtils.getProviderUrl(),dn,password);
+		ldapPassWordValid.openConnection();
+		if(ldapPassWordValid.getCtx()!=null){
+			_logger.debug("Directory user " + username + "  is validate .");
+			ldapPassWordValid.close();
+			return true;
+		}
+		return false;
+	}
+	
+	public LdapUtils getLdapUtils() {
+		return ldapUtils;
+	}
+	public void setLdapUtils(LdapUtils ldapUtils) {
+		this.ldapUtils = ldapUtils;
+	}
+	public String getFilterAttribute() {
+		return filterAttribute;
+	}
+	public void setFilterAttribute(String filterAttribute) {
+		this.filterAttribute = filterAttribute;
+	}
+
+	@Override
+	public boolean isMapping() {
+		return mapping;
+	}
+
+	public void setMapping(boolean mapping) {
+		this.mapping = mapping;
+	}
+
+}

+ 119 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/support/jwt/HttpJwtEntryPoint.java

@@ -0,0 +1,119 @@
+/*
+ * 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.dromara.maxkey.authn.support.jwt;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.jwt.AuthJwt;
+import org.dromara.maxkey.authn.jwt.AuthTokenService;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.entity.Message;
+import org.dromara.maxkey.web.WebConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.nimbusds.jwt.SignedJWT;
+
+
+@RestController
+@RequestMapping(value = "/login")
+public class HttpJwtEntryPoint {
+	private static final Logger _logger = LoggerFactory.getLogger(HttpJwtEntryPoint.class);
+    
+	@Autowired
+  	ApplicationConfig applicationConfig;
+    
+  	@Autowired
+    AbstractAuthenticationProvider authenticationProvider ;
+  	
+  	@Autowired
+	AuthTokenService authTokenService;
+  	
+    @Autowired
+	JwtLoginService jwtLoginService;
+	
+	@RequestMapping(value={"/jwt"}, produces = {MediaType.APPLICATION_JSON_VALUE},method={RequestMethod.GET,RequestMethod.POST})
+	public Message<AuthJwt> jwt(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
+		try {
+			//for jwt Login
+			 _logger.debug("jwt : {}" , jwt);
+	
+			 SignedJWT signedJWT = jwtLoginService.jwtTokenValidation(jwt);
+			 
+			 if(signedJWT != null) {
+				 String username =signedJWT.getJWTClaimsSet().getSubject();
+				 LoginCredential loginCredential =new LoginCredential(username,"",ConstsLoginType.JWT);
+				 Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
+				 _logger.debug("JWT Logined in , username {}" , username);
+				 AuthJwt authJwt = authTokenService.genAuthJwt(authentication);
+		 		 return new Message<>(authJwt);
+			 }
+		}catch(Exception e) {
+			_logger.error("Exception ",e);
+		}
+		
+		 return new Message<>(Message.FAIL);
+	}
+	
+	/**
+	 * trust same HS512
+	 * @param jwt
+	 * @return
+	 */
+	@RequestMapping(value={"/jwt/trust"}, produces = {MediaType.APPLICATION_JSON_VALUE},method={RequestMethod.GET,RequestMethod.POST})
+	public Message<AuthJwt> jwtTrust(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
+		try {
+			//for jwt Login
+			 _logger.debug("jwt : {}" , jwt);
+
+			 if(authTokenService.validateJwtToken(jwt)) {
+				 String username =authTokenService.resolve(jwt).getSubject();
+				 LoginCredential loginCredential =new LoginCredential(username,"",ConstsLoginType.JWT);
+				 Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
+				 _logger.debug("JWT Logined in , username {}" , username);
+				 AuthJwt authJwt = authTokenService.genAuthJwt(authentication);
+		 		 return new Message<>(authJwt);
+			 }
+		}catch(Exception e) {
+			_logger.error("Exception ",e);
+		}
+		
+		 return new Message<>(Message.FAIL);
+	}
+
+
+	public void setApplicationConfig(ApplicationConfig applicationConfig) {
+		this.applicationConfig = applicationConfig;
+	}
+
+	public void setAuthenticationProvider(AbstractAuthenticationProvider authenticationProvider) {
+		this.authenticationProvider = authenticationProvider;
+	}
+
+	public void setJwtLoginService(JwtLoginService jwtLoginService) {
+		this.jwtLoginService = jwtLoginService;
+	}
+	
+}

+ 135 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/authn/support/jwt/JwtLoginService.java

@@ -0,0 +1,135 @@
+/*
+ * 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.dromara.maxkey.authn.support.jwt;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import com.nimbusds.jwt.SignedJWT;
+import java.util.Date;
+import java.util.UUID;
+
+import org.dromara.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
+import org.dromara.maxkey.web.WebContext;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class JwtLoginService {
+    private static final Logger _logger = LoggerFactory.getLogger(JwtLoginService.class);
+
+    String issuer;
+    
+    DefaultJwtSigningAndValidationService jwtSignerValidationService;
+    
+    public JwtLoginService(
+            DefaultJwtSigningAndValidationService jwtSignerValidationService,
+            String issuer
+            ) {
+        this.jwtSignerValidationService = jwtSignerValidationService;
+        this.issuer = issuer;
+    }
+
+    public String buildLoginJwt() {
+        _logger.debug("build Login JWT .");
+
+        DateTime currentDateTime = DateTime.now();
+        Date expirationTime = currentDateTime.plusMinutes(5).toDate();
+        _logger.debug("Expiration Time : " + expirationTime);
+        JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder().subject(WebContext.getSession().getId())
+                .expirationTime(expirationTime).issuer(getIssuer())
+                .issueTime(currentDateTime.toDate()).jwtID(UUID.randomUUID().toString()).build();
+
+        JWT jwtToken = new PlainJWT(jwtClaims);
+
+        _logger.info("JWT Claims : " + jwtClaims.toString());
+
+        JWSAlgorithm signingAlg = jwtSignerValidationService.getDefaultSigningAlgorithm();
+
+        jwtToken = new SignedJWT(new JWSHeader(signingAlg), jwtClaims);
+        // sign it with the server's key
+        jwtSignerValidationService.signJwt((SignedJWT) jwtToken);
+
+        String tokenString = jwtToken.serialize();
+        _logger.debug("JWT Token : " + tokenString);
+        return tokenString;
+    }
+
+    public SignedJWT jwtTokenValidation(String jwt) {
+        SignedJWT signedJWT = null;
+        JWTClaimsSet jwtClaimsSet = null;
+        try {
+            RSASSAVerifier rsaSSAVerifier = 
+                    new RSASSAVerifier(((RSAKey) jwtSignerValidationService.getAllPublicKeys()
+                            .get(jwtSignerValidationService.getDefaultSignerKeyId())).toRSAPublicKey());
+
+            signedJWT = SignedJWT.parse(jwt);
+            
+            if (signedJWT.verify(rsaSSAVerifier)) {
+            	 jwtClaimsSet = signedJWT.getJWTClaimsSet();
+            	 boolean isIssuerMatches = jwtClaimsSet.getIssuer().equals(getIssuer());
+            	 boolean isExpiration = (new DateTime()).isBefore(
+            	             jwtClaimsSet.getExpirationTime().getTime());
+            	 
+                 _logger.debug("Signed JWT {}" , signedJWT.getPayload());
+                 _logger.debug("Subject is {}" , jwtClaimsSet.getSubject());
+                 _logger.debug("ExpirationTime  Validation {}" ,isExpiration);
+                 _logger.debug("JWT ClaimsSet Issuer {}, Metadata Issuer {}, Issuer is matches {}" ,
+                                jwtClaimsSet.getIssuer(), getIssuer(), isIssuerMatches
+                        );
+
+                 if ( isIssuerMatches && isExpiration ) {
+                    return signedJWT;
+                 }
+            }else { 
+                _logger.debug("JWT Signer Verify false.");
+            }
+        } catch (java.text.ParseException e) {
+            // Invalid signed JWT encoding
+            _logger.error("Invalid signed JWT encoding ",e);
+        } catch (JOSEException e) {
+            _logger.error("JOSEException ",e);
+        }
+        return null;
+    }
+
+    public void setJwtSignerValidationService(DefaultJwtSigningAndValidationService jwtSignerValidationService) {
+        this.jwtSignerValidationService = jwtSignerValidationService;
+    }
+
+	public DefaultJwtSigningAndValidationService getJwtSignerValidationService() {
+		return jwtSignerValidationService;
+	}
+
+    public String getIssuer() {
+        return issuer;
+    }
+
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+    
+    
+
+}

+ 117 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/autoconfigure/AuthnProviderAutoConfiguration.java

@@ -0,0 +1,117 @@
+/*
+ * 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.dromara.maxkey.autoconfigure;
+
+import org.dromara.maxkey.authn.jwt.AuthTokenService;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.provider.AuthenticationProviderFactory;
+import org.dromara.maxkey.authn.provider.impl.*;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.password.sms.SmsOtpAuthnService;
+import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;
+import org.dromara.maxkey.persistence.repository.LoginRepository;
+import org.dromara.maxkey.persistence.repository.PasswordPolicyValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+
+@AutoConfiguration
+public class AuthnProviderAutoConfiguration {
+    static final  Logger _logger = LoggerFactory.getLogger(AuthnProviderAutoConfiguration.class);
+
+    @Bean
+     AbstractAuthenticationProvider authenticationProvider(
+    		NormalAuthenticationProvider normalAuthenticationProvider,
+    		MobileAuthenticationProvider mobileAuthenticationProvider,
+    		TrustedAuthenticationProvider trustedAuthenticationProvider
+    		) {
+    	AuthenticationProviderFactory authenticationProvider = new AuthenticationProviderFactory();
+    	authenticationProvider.addAuthenticationProvider(normalAuthenticationProvider);
+    	authenticationProvider.addAuthenticationProvider(mobileAuthenticationProvider);
+    	authenticationProvider.addAuthenticationProvider(trustedAuthenticationProvider);
+    	return authenticationProvider;
+    }
+
+    @Bean
+    NormalAuthenticationProvider normalAuthenticationProvider(
+    		AbstractAuthenticationRealm authenticationRealm,
+    		ApplicationConfig applicationConfig,
+    	    SessionManager sessionManager,
+    	    AuthTokenService authTokenService
+    		) {
+    	_logger.debug("init authentication Provider .");
+    	return new NormalAuthenticationProvider(
+        		authenticationRealm,
+        		applicationConfig,
+        		sessionManager,
+        		authTokenService
+        	);
+    }
+
+    @Bean
+    MobileAuthenticationProvider mobileAuthenticationProvider(
+    		AbstractAuthenticationRealm authenticationRealm,
+    		ApplicationConfig applicationConfig,
+    	    SmsOtpAuthnService smsAuthnService,
+    	    SessionManager sessionManager
+    		) {
+    	_logger.debug("init Mobile authentication Provider .");
+    	return new MobileAuthenticationProvider(
+        		authenticationRealm,
+        		applicationConfig,
+        		smsAuthnService,
+        		sessionManager
+        	);
+    }
+    
+    @Bean
+    TrustedAuthenticationProvider trustedAuthenticationProvider(
+    		AbstractAuthenticationRealm authenticationRealm,
+    		ApplicationConfig applicationConfig,
+    	    SessionManager sessionManager
+    		) {
+    	_logger.debug("init Mobile authentication Provider .");
+    	return new TrustedAuthenticationProvider(
+        		authenticationRealm,
+        		applicationConfig,
+        		sessionManager
+        	);
+    }
+
+    @Bean
+    PasswordPolicyValidator passwordPolicyValidator(JdbcTemplate jdbcTemplate,MessageSource messageSource) {
+        return new PasswordPolicyValidator(jdbcTemplate,messageSource);
+    }
+
+    @Bean
+    LoginRepository loginRepository(JdbcTemplate jdbcTemplate) {
+        return new LoginRepository(jdbcTemplate);
+    }
+
+    @Bean
+    LoginHistoryRepository loginHistoryRepository(JdbcTemplate jdbcTemplate) {
+        return new LoginHistoryRepository(jdbcTemplate);
+    }
+
+}

+ 89 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/java/org/dromara/maxkey/autoconfigure/JwtAuthnAutoConfiguration.java

@@ -0,0 +1,89 @@
+/*
+ * 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.dromara.maxkey.autoconfigure;
+
+import com.nimbusds.jose.JOSEException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+
+import org.dromara.maxkey.authn.support.jwt.JwtLoginService;
+import org.dromara.maxkey.crypto.jose.keystore.JWKSetKeyStore;
+import org.dromara.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.ClassPathResource;
+
+
+@AutoConfiguration
+public class JwtAuthnAutoConfiguration  {
+    private static final  Logger _logger = LoggerFactory.getLogger(JwtAuthnAutoConfiguration.class);
+
+    /**
+     * jwt Login JwkSetKeyStore.
+     * @return
+     */
+    @Bean
+    JWKSetKeyStore jwtLoginJwkSetKeyStore() {
+        JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore();
+        ClassPathResource classPathResource = new ClassPathResource("/config/loginjwkkeystore.jwks");
+        jwkSetKeyStore.setLocation(classPathResource);
+        _logger.debug("JWT Login JwkSet KeyStore init.");
+        return jwkSetKeyStore;
+    }
+
+    /**
+     * jwt Login ValidationService.
+     * @return
+     * @throws JOSEException
+     * @throws InvalidKeySpecException 
+     * @throws NoSuchAlgorithmException 
+     */
+    @Bean
+    DefaultJwtSigningAndValidationService jwtLoginValidationService(
+            @Qualifier("jwtLoginJwkSetKeyStore") JWKSetKeyStore jwtLoginJwkSetKeyStore)
+            throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
+        DefaultJwtSigningAndValidationService jwtSignerValidationService = 
+                new DefaultJwtSigningAndValidationService(jwtLoginJwkSetKeyStore);
+        jwtSignerValidationService.setDefaultSignerKeyId("maxkey_rsa");
+        jwtSignerValidationService.setDefaultSigningAlgorithmName("RS256");
+        _logger.debug("JWT Login Signing and Validation init.");
+        return jwtSignerValidationService;
+    }
+
+    /**
+     * Jwt LoginService.
+     * @return
+     */
+    @Bean
+    JwtLoginService jwtLoginService(
+            @Value("${maxkey.login.jwt.issuer}")
+            String issuer,
+            @Qualifier("jwtLoginValidationService")
+            DefaultJwtSigningAndValidationService jwtLoginValidationService) {
+        JwtLoginService jwtLoginService = new JwtLoginService(
+                    jwtLoginValidationService,
+                    issuer
+                );
+        _logger.debug("JWT Login Service init.");
+        return jwtLoginService;
+    }
+}

+ 2 - 0
maxkey-authentications/maxkey-authentication-provider-mgt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1,2 @@
+org.dromara.maxkey.autoconfigure.AuthnProviderAutoConfiguration
+org.dromara.maxkey.autoconfigure.JwtAuthnAutoConfiguration

+ 1 - 1
maxkey-webs/maxkey-web-mgt/build.gradle

@@ -51,7 +51,7 @@ dependencies {
 	implementation project(":maxkey-starter:maxkey-starter-web")
 	
 	implementation project(":maxkey-authentications:maxkey-authentication-core")
-	implementation project(":maxkey-authentications:maxkey-authentication-provider")
+	implementation project(":maxkey-authentications:maxkey-authentication-provider-mgt")
 	
 	implementation project(":maxkey-protocols:maxkey-protocol-authorize")
    	implementation project(":maxkey-protocols:maxkey-protocol-oauth-2.0")

+ 4 - 5
maxkey-webs/maxkey-web-mgt/src/main/java/org/dromara/maxkey/web/contorller/LoginEntryPoint.java

@@ -32,11 +32,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.http.MediaType;
-
 
 /**
  * @author Crystal.Sea
@@ -60,12 +60,11 @@ public class LoginEntryPoint {
 	 * init login
 	 * @return
 	 */
- 	@RequestMapping(value={"/get"}, produces = {MediaType.APPLICATION_JSON_VALUE})
+ 	@GetMapping("/get")
 	public Message<?> get() {
 		logger.debug("/login.");
 		
 		HashMap<String , Object> model = new HashMap<String , Object>();
-		model.put("isRemeberMe", applicationConfig.getLoginConfig().isRemeberMe());
 		Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
 		model.put("inst", inst);
 		if(applicationConfig.getLoginConfig().isCaptcha()) {
@@ -75,7 +74,7 @@ public class LoginEntryPoint {
 		return new Message<HashMap<String , Object>>(model);
 	}
  	
- 	@RequestMapping(value={"/signin"}, produces = {MediaType.APPLICATION_JSON_VALUE})
+ 	@PostMapping("/signin")
 	public Message<?> signin( @RequestBody LoginCredential loginCredential) {
  		Message<AuthJwt> authJwtMessage = new Message<AuthJwt>(Message.FAIL);
  		if(authTokenService.validateJwtToken(loginCredential.getState())){

+ 1 - 0
settings.gradle

@@ -36,6 +36,7 @@ include ('maxkey-starter:maxkey-starter-web')
 //authentications
 include ('maxkey-authentications:maxkey-authentication-core')
 include ('maxkey-authentications:maxkey-authentication-provider')
+include ('maxkey-authentications:maxkey-authentication-provider-mgt')
 
 //rest apis
 include ('maxkey-web-apis:maxkey-web-api-rest')