二维码跳转登录
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package org.dromara.maxkey.authn;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 16/8/2024 AM10:54
|
||||
*/
|
||||
|
||||
|
||||
public class QrCodeCredentialDto {
|
||||
|
||||
|
||||
@NotEmpty(message = "jwtToken不能为空")
|
||||
@Schema(name = "jwtToken", description = "token")
|
||||
String jwtToken;
|
||||
|
||||
@NotEmpty(message = "返回码不能为空")
|
||||
@Schema(name = "code", description = "返回码")
|
||||
String code;
|
||||
|
||||
public @NotEmpty(message = "jwtToken不能为空") String getJwtToken() {
|
||||
return jwtToken;
|
||||
}
|
||||
|
||||
public void setJwtToken(@NotEmpty(message = "jwtToken不能为空") String jwtToken) {
|
||||
this.jwtToken = jwtToken;
|
||||
}
|
||||
|
||||
public @NotEmpty(message = "返回码不能为空") String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(@NotEmpty(message = "返回码不能为空") String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.dromara.maxkey.authn;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 16/8/2024 PM4:28
|
||||
*/
|
||||
public class ScanCode {
|
||||
|
||||
@NotEmpty(message = "二维码内容不能为空")
|
||||
String code;
|
||||
|
||||
@NotEmpty(message = "登录方式不能为空")
|
||||
String authType;
|
||||
|
||||
public @NotEmpty(message = "二维码内容不能为空") String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(@NotEmpty(message = "二维码内容不能为空") String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public @NotEmpty(message = "登录方式不能为空") String getAuthType() {
|
||||
return authType;
|
||||
}
|
||||
|
||||
public void setAuthType(@NotEmpty(message = "登录方式不能为空") String authType) {
|
||||
this.authType = authType;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 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.session;
|
||||
|
||||
@@ -27,16 +27,16 @@ public interface SessionManager {
|
||||
public void create(String sessionId, Session session);
|
||||
|
||||
public Session remove(String sessionId);
|
||||
|
||||
|
||||
public Session get(String sessionId);
|
||||
|
||||
|
||||
public Session refresh(String sessionId ,LocalDateTime refreshTime);
|
||||
|
||||
|
||||
public Session refresh(String sessionId);
|
||||
|
||||
|
||||
public List<HistoryLogin> querySessions();
|
||||
|
||||
|
||||
public int getValiditySeconds();
|
||||
|
||||
|
||||
public void terminate(String sessionId,String userId,String username);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
/*
|
||||
* 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.web;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
|
||||
import com.nimbusds.jwt.SignedJWT;
|
||||
import org.dromara.maxkey.authn.SignPrincipal;
|
||||
import org.dromara.maxkey.authn.jwt.AuthTokenService;
|
||||
import org.dromara.maxkey.authn.session.Session;
|
||||
@@ -37,14 +38,14 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
public class AuthorizationUtils {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(AuthorizationUtils.class);
|
||||
|
||||
|
||||
public static final class BEARERTYPE{
|
||||
|
||||
|
||||
public static final String CONGRESS = "congress";
|
||||
|
||||
|
||||
public static final String AUTHORIZATION = "Authorization";
|
||||
}
|
||||
|
||||
|
||||
public static void authenticateWithCookie(
|
||||
HttpServletRequest request,
|
||||
AuthTokenService authTokenService,
|
||||
@@ -55,12 +56,12 @@ public class AuthorizationUtils {
|
||||
String authorization = authCookie.getValue();
|
||||
_logger.trace("Try congress authenticate .");
|
||||
doJwtAuthenticate(BEARERTYPE.CONGRESS,authorization,authTokenService,sessionManager);
|
||||
}else {
|
||||
}else {
|
||||
_logger.debug("cookie is null , clear authentication .");
|
||||
clearAuthentication();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void authenticate(
|
||||
HttpServletRequest request,
|
||||
AuthTokenService authTokenService,
|
||||
@@ -71,9 +72,9 @@ public class AuthorizationUtils {
|
||||
_logger.trace("Try Authorization authenticate .");
|
||||
doJwtAuthenticate(BEARERTYPE.AUTHORIZATION,authorization,authTokenService,sessionManager);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void doJwtAuthenticate(
|
||||
String bearerType,
|
||||
String authorization,
|
||||
@@ -99,17 +100,25 @@ public class AuthorizationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Session getSession(SessionManager sessionManager, String authorization) throws ParseException {
|
||||
_logger.debug("get session by authorization {}", authorization);
|
||||
SignedJWT signedJWT = SignedJWT.parse(authorization);
|
||||
String sessionId = signedJWT.getJWTClaimsSet().getJWTID();
|
||||
_logger.debug("sessionId {}", sessionId);
|
||||
return sessionManager.get(sessionId);
|
||||
}
|
||||
|
||||
|
||||
public static Authentication getAuthentication() {
|
||||
Authentication authentication = (Authentication) getAuthentication(WebContext.getRequest());
|
||||
return authentication;
|
||||
}
|
||||
|
||||
|
||||
public static Authentication getAuthentication(HttpServletRequest request) {
|
||||
Authentication authentication = (Authentication) request.getSession().getAttribute(WebConstants.AUTHENTICATION);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
|
||||
//set Authentication to http session
|
||||
public static void setAuthentication(Authentication authentication) {
|
||||
WebContext.setAttribute(WebConstants.AUTHENTICATION, authentication);
|
||||
@@ -118,24 +127,24 @@ public class AuthorizationUtils {
|
||||
public static void clearAuthentication() {
|
||||
WebContext.removeAttribute(WebConstants.AUTHENTICATION);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAuthenticated() {
|
||||
return getAuthentication() != null;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isNotAuthenticated() {
|
||||
return ! isAuthenticated();
|
||||
}
|
||||
|
||||
|
||||
public static SignPrincipal getPrincipal() {
|
||||
Authentication authentication = getAuthentication();
|
||||
return getPrincipal(authentication);
|
||||
}
|
||||
|
||||
|
||||
public static SignPrincipal getPrincipal(Authentication authentication) {
|
||||
return authentication == null ? null : (SignPrincipal) authentication.getPrincipal();
|
||||
}
|
||||
|
||||
|
||||
public static UserInfo getUserInfo(Authentication authentication) {
|
||||
UserInfo userInfo = null;
|
||||
SignPrincipal principal = getPrincipal(authentication);
|
||||
@@ -144,9 +153,9 @@ public class AuthorizationUtils {
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
|
||||
public static UserInfo getUserInfo() {
|
||||
return getUserInfo(getAuthentication());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@@ -45,37 +45,41 @@ 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 =
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
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"));
|
||||
}
|
||||
@@ -83,7 +87,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
public abstract String getProviderName();
|
||||
|
||||
public abstract Authentication doAuthenticate(LoginCredential authentication);
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean supports(Class authentication) {
|
||||
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
|
||||
@@ -92,13 +96,13 @@ public abstract class AbstractAuthenticationProvider {
|
||||
public Authentication authenticate(LoginCredential authentication){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Authentication authenticate(LoginCredential authentication,boolean trusted) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* createOnlineSession
|
||||
* createOnlineSession
|
||||
* @param credential
|
||||
* @param userInfo
|
||||
* @return
|
||||
@@ -112,7 +116,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
|
||||
List<GrantedAuthority> grantedAuthoritys = authenticationRealm.grantAuthority(userInfo);
|
||||
principal.setAuthenticated(true);
|
||||
|
||||
|
||||
for(GrantedAuthority administratorsAuthority : grantedAdministratorsAuthoritys) {
|
||||
if(grantedAuthoritys.contains(administratorsAuthority)) {
|
||||
principal.setRoleAdministrators(true);
|
||||
@@ -120,37 +124,37 @@ public abstract class AbstractAuthenticationProvider {
|
||||
}
|
||||
}
|
||||
_logger.debug("Granted Authority {}" , grantedAuthoritys);
|
||||
|
||||
|
||||
principal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys));
|
||||
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
principal,
|
||||
"PASSWORD",
|
||||
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
|
||||
@@ -164,7 +168,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
} else {
|
||||
_logger.debug("User Login. ");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return userInfo;
|
||||
@@ -172,7 +176,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* check input password empty.
|
||||
*
|
||||
*
|
||||
* @param password String
|
||||
* @return
|
||||
*/
|
||||
@@ -185,7 +189,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* check input username or password empty.
|
||||
*
|
||||
*
|
||||
* @param email String
|
||||
* @return
|
||||
*/
|
||||
@@ -198,7 +202,7 @@ public abstract class AbstractAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* check input username empty.
|
||||
*
|
||||
*
|
||||
* @param username String
|
||||
* @return
|
||||
*/
|
||||
@@ -219,8 +223,8 @@ public abstract class AbstractAuthenticationProvider {
|
||||
loginUser.setDisplayName("not exist");
|
||||
loginUser.setLoginCount(0);
|
||||
authenticationRealm.insertLoginHistory(
|
||||
loginUser,
|
||||
ConstsLoginType.LOCAL,
|
||||
loginUser,
|
||||
ConstsLoginType.LOCAL,
|
||||
"",
|
||||
i18nMessage,
|
||||
WebConstants.LOGIN_RESULT.USER_NOT_EXIST);
|
||||
@@ -228,22 +232,22 @@ public abstract class AbstractAuthenticationProvider {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected boolean statusValid(LoginCredential loginCredential , UserInfo userInfo) {
|
||||
if(userInfo.getIsLocked()==ConstsStatus.LOCK) {
|
||||
authenticationRealm.insertLoginHistory(
|
||||
userInfo,
|
||||
loginCredential.getAuthType(),
|
||||
loginCredential.getProvider(),
|
||||
loginCredential.getCode(),
|
||||
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(),
|
||||
authenticationRealm.insertLoginHistory(
|
||||
userInfo,
|
||||
loginCredential.getAuthType(),
|
||||
loginCredential.getProvider(),
|
||||
loginCredential.getCode(),
|
||||
WebConstants.LOGIN_RESULT.USER_INACTIVE
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.dromara.maxkey.authn.provider.impl;
|
||||
|
||||
import org.dromara.maxkey.authn.LoginCredential;
|
||||
import org.dromara.maxkey.authn.SignPrincipal;
|
||||
import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.provider.scancode.ScanCodeService;
|
||||
import org.dromara.maxkey.authn.provider.scancode.ScanCodeState;
|
||||
|
||||
import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
|
||||
import org.dromara.maxkey.authn.session.SessionManager;
|
||||
|
||||
import org.dromara.maxkey.constants.ConstsLoginType;
|
||||
import org.dromara.maxkey.crypto.password.PasswordReciprocal;
|
||||
import org.dromara.maxkey.entity.idm.UserInfo;
|
||||
;
|
||||
import org.dromara.maxkey.web.WebConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 16/8/2024 PM4:54
|
||||
*/
|
||||
public class ScanCodeAuthenticationProvider extends AbstractAuthenticationProvider {
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(ScanCodeAuthenticationProvider.class);
|
||||
|
||||
@Autowired
|
||||
ScanCodeService scanCodeService;
|
||||
|
||||
public ScanCodeAuthenticationProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ScanCodeAuthenticationProvider(
|
||||
AbstractAuthenticationRealm authenticationRealm,
|
||||
SessionManager sessionManager) {
|
||||
this.authenticationRealm = authenticationRealm;
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return "scancode" + PROVIDER_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication doAuthenticate(LoginCredential loginCredential) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken = null;
|
||||
|
||||
String encodeTicket = PasswordReciprocal.getInstance().decoder(loginCredential.getUsername());
|
||||
|
||||
ScanCodeState scanCodeState = scanCodeService.consume(encodeTicket);
|
||||
|
||||
if (Objects.isNull(scanCodeState)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SignPrincipal signPrincipal = (SignPrincipal) sessionManager.get(scanCodeState.getSessionId()).getAuthentication().getPrincipal();
|
||||
//获取用户信息
|
||||
UserInfo userInfo = signPrincipal.getUserInfo();
|
||||
|
||||
isUserExist(loginCredential , userInfo);
|
||||
|
||||
statusValid(loginCredential , 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);
|
||||
|
||||
return authenticationToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.dromara.maxkey.authn.provider.scancode;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dromara.maxkey.authn.session.Session;
|
||||
import org.dromara.maxkey.authn.session.SessionManager;
|
||||
import org.dromara.maxkey.exception.BusinessException;
|
||||
import org.dromara.maxkey.persistence.cache.MomentaryService;
|
||||
import org.dromara.maxkey.util.IdGenerator;
|
||||
import org.dromara.maxkey.util.JsonUtils;
|
||||
import org.dromara.maxkey.util.TimeJsonUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 15/8/2024 AM9:49
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public class ScanCodeService {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(ScanCodeService.class);
|
||||
|
||||
static final String SCANCODE_TICKET = "login:scancode:%s";
|
||||
|
||||
static final String SCANCODE_CONFIRM = "login:scancode:confirm:%s";
|
||||
|
||||
public static class STATE {
|
||||
public static final String SCANED = "scaned";
|
||||
public static final String CONFIRMED = "confirmed";
|
||||
public static final String CANCELED = "canceled";
|
||||
|
||||
public static final String CANCEL = "cancel";
|
||||
public static final String CONFIRM = "confirm";
|
||||
}
|
||||
|
||||
int validitySeconds = 60 * 3; //default 3 minutes.
|
||||
|
||||
int cancelValiditySeconds = 60 * 1; //default 1 minutes.
|
||||
|
||||
|
||||
@Autowired
|
||||
IdGenerator idGenerator;
|
||||
|
||||
@Autowired
|
||||
MomentaryService momentaryService;
|
||||
|
||||
private String getKey(String ticket) {
|
||||
return SCANCODE_TICKET.formatted(ticket);
|
||||
}
|
||||
|
||||
private String getConfirmKey(Long sessionId) {
|
||||
return SCANCODE_CONFIRM.formatted(sessionId);
|
||||
}
|
||||
|
||||
public String createTicket() {
|
||||
String ticket = idGenerator.generate();
|
||||
ScanCodeState scanCodeState = new ScanCodeState();
|
||||
scanCodeState.setState("unscanned");
|
||||
|
||||
// 将对象序列化为 JSON 字符串
|
||||
String jsonString = TimeJsonUtils.gsonToString(scanCodeState);
|
||||
momentaryService.put(getKey(ticket), "", jsonString);
|
||||
_logger.info("Ticket {} , Duration {}", ticket, jsonString);
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public boolean validateTicket(String ticket, Session session) {
|
||||
String key = getKey(ticket);
|
||||
Object value = momentaryService.get(key, "");
|
||||
if (Objects.isNull(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScanCodeState scanCodeState = new ScanCodeState();
|
||||
scanCodeState.setState("scanned");
|
||||
scanCodeState.setTicket(ticket);
|
||||
scanCodeState.setSessionId(session.getId());
|
||||
momentaryService.put(key, "", TimeJsonUtils.gsonToString(scanCodeState));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ScanCodeState consume(String ticket){
|
||||
String key = getKey(ticket);
|
||||
Object o = momentaryService.get(key, "");
|
||||
if (Objects.nonNull(o)) {
|
||||
String redisObject = o.toString();
|
||||
ScanCodeState scanCodeState = TimeJsonUtils.gsonStringToObject(redisObject, ScanCodeState.class);
|
||||
if ("scanned".equals(scanCodeState.getState())) {
|
||||
momentaryService.remove(key, "");
|
||||
return scanCodeState;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
throw new BusinessException(20004, "该二维码失效");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.dromara.maxkey.authn.provider.scancode;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.dromara.maxkey.authn.session.Session;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 16/8/2024 PM5:42
|
||||
*/
|
||||
public class ScanCodeState {
|
||||
|
||||
String sessionId;
|
||||
|
||||
String ticket;
|
||||
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||
Long confirmKey;
|
||||
|
||||
String state;
|
||||
|
||||
public String getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public void setSessionId(String sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public Long getConfirmKey() {
|
||||
return confirmKey;
|
||||
}
|
||||
|
||||
public void setConfirmKey(Long confirmKey) {
|
||||
this.confirmKey = confirmKey;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.dromara.maxkey.authn.provider.scancode;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: orangeBabu
|
||||
* @time: 17/8/2024 PM5:08
|
||||
*/
|
||||
public class ScancodeSignInfo {
|
||||
|
||||
String username;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.provider.AuthenticationProviderFactory;
|
||||
import org.dromara.maxkey.authn.provider.impl.MobileAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.provider.impl.NormalAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.provider.impl.ScanCodeAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.provider.impl.TrustedAuthenticationProvider;
|
||||
import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
|
||||
import org.dromara.maxkey.authn.session.SessionManager;
|
||||
@@ -44,21 +45,23 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@AutoConfiguration
|
||||
public class AuthnProviderAutoConfiguration {
|
||||
static final Logger _logger = LoggerFactory.getLogger(AuthnProviderAutoConfiguration.class);
|
||||
|
||||
|
||||
@Bean
|
||||
public AbstractAuthenticationProvider authenticationProvider(
|
||||
NormalAuthenticationProvider normalAuthenticationProvider,
|
||||
MobileAuthenticationProvider mobileAuthenticationProvider,
|
||||
TrustedAuthenticationProvider trustedAuthenticationProvider
|
||||
TrustedAuthenticationProvider trustedAuthenticationProvider,
|
||||
ScanCodeAuthenticationProvider scanCodeAuthenticationProvider
|
||||
) {
|
||||
AuthenticationProviderFactory authenticationProvider = new AuthenticationProviderFactory();
|
||||
authenticationProvider.addAuthenticationProvider(normalAuthenticationProvider);
|
||||
authenticationProvider.addAuthenticationProvider(mobileAuthenticationProvider);
|
||||
authenticationProvider.addAuthenticationProvider(trustedAuthenticationProvider);
|
||||
|
||||
authenticationProvider.addAuthenticationProvider(scanCodeAuthenticationProvider);
|
||||
|
||||
return authenticationProvider;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public NormalAuthenticationProvider normalAuthenticationProvider(
|
||||
AbstractAuthenticationRealm authenticationRealm,
|
||||
@@ -74,7 +77,18 @@ public class AuthnProviderAutoConfiguration {
|
||||
authTokenService
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public ScanCodeAuthenticationProvider scanCodeAuthenticationProvider(
|
||||
AbstractAuthenticationRealm authenticationRealm,
|
||||
SessionManager sessionManager
|
||||
) {
|
||||
return new ScanCodeAuthenticationProvider(
|
||||
authenticationRealm,
|
||||
sessionManager
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MobileAuthenticationProvider mobileAuthenticationProvider(
|
||||
AbstractAuthenticationRealm authenticationRealm,
|
||||
@@ -104,22 +118,22 @@ public class AuthnProviderAutoConfiguration {
|
||||
sessionManager
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public PasswordPolicyValidator passwordPolicyValidator(JdbcTemplate jdbcTemplate,MessageSource messageSource) {
|
||||
return new PasswordPolicyValidator(jdbcTemplate,messageSource);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public LoginRepository loginRepository(JdbcTemplate jdbcTemplate) {
|
||||
return new LoginRepository(jdbcTemplate);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public LoginHistoryRepository loginHistoryRepository(JdbcTemplate jdbcTemplate) {
|
||||
return new LoginHistoryRepository(jdbcTemplate);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remeberMeService .
|
||||
* @return
|
||||
@@ -135,5 +149,5 @@ public class AuthnProviderAutoConfiguration {
|
||||
return new JdbcRemeberMeManager(
|
||||
jdbcTemplate,applicationConfig,authTokenService,validity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user