提交 7bba47a4 编写于 作者: M MaxKey

Provider

上级 586e473e
...@@ -3,6 +3,9 @@ description = "maxkey-authentication-captcha" ...@@ -3,6 +3,9 @@ description = "maxkey-authentication-captcha"
dependencies { dependencies {
implementation project(":maxkey-common")
implementation project(":maxkey-core")
implementation project(":maxkey-authentications:maxkey-authentication-core")
//local jars //local jars
implementation fileTree(dir: '../maxkey-lib/', include: '*/*.jar') implementation fileTree(dir: '../maxkey-lib/', include: '*/*.jar')
} }
\ No newline at end of file
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.web.contorller;
public class ImageCaptcha {
String id;
String image;
public ImageCaptcha(String id, String image) {
super();
this.id = id;
this.image = image;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.web.contorller;
import com.google.code.kaptcha.Producer;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* ImageCaptchaEndpoint Producer captcha.
* @author Crystal.Sea
*
*/
@Controller
public class ImageCaptchaBase64Endpoint {
private static final Logger _logger = LoggerFactory.getLogger(ImageCaptchaBase64Endpoint.class);
public static final String IMAGE_GIF = "image/gif";
public static final String KAPTCHA_SESSION_KEY = "kaptcha_session_key";
@Autowired
private Producer captchaProducer;
/**
* captcha image Producer.
*
* @param request HttpServletRequest
* @param response HttpServletResponse
*/
@RequestMapping(value = "/captcha/base64")
public void captchaHandleRequest(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value="captcha",required=false,defaultValue="text") String captchaType) {
try {
String kaptchaText = captchaProducer.createText();
if (captchaType.equalsIgnoreCase("Arithmetic")) {
Integer intParamA = Integer.valueOf(kaptchaText.substring(0, 1));
Integer intParamB = Integer.valueOf(kaptchaText.substring(1, 2));
Integer calculateValue = 0;
if ((intParamA > intParamB) && ((intParamA + intParamB) % 5 > 3)) {
calculateValue = intParamA - intParamB;
kaptchaText = intParamA + "-" + intParamB + "=?";
} else {
calculateValue = intParamA + intParamB;
kaptchaText = intParamA + "+" + intParamB + "=?";
}
_logger.trace("Sesssion id " + request.getSession().getId()
+ " , Arithmetic calculate Value is " + calculateValue);
request.getSession().setAttribute(
KAPTCHA_SESSION_KEY, calculateValue + "");
} else {
// store the text in the session
request.getSession().setAttribute(KAPTCHA_SESSION_KEY, kaptchaText);
}
_logger.trace("Sesssion id " + request.getSession().getId()
+ " , Captcha Text is " + kaptchaText);
// create the image with the text
BufferedImage bufferedImage = captchaProducer.createImage(kaptchaText);
producerImage(request,response,bufferedImage);
} catch (Exception e) {
_logger.error("captcha Producer Error " + e.getMessage());
}
}
/**
* producerImage.
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param bufferedImage BufferedImage
* @throws IOException error
*/
public static void producerImage(HttpServletRequest request,
HttpServletResponse response,
BufferedImage bufferedImage) throws IOException {
// Set to expire far in the past.
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg/gif
//response.setContentType(IMAGE_GIF);
_logger.trace("create the image");
// create the image
if (bufferedImage != null) {
ServletOutputStream out = response.getOutputStream();
// write the data out
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", stream);
String b64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(stream.toByteArray());
out.print(b64Image);
_logger.debug("b64Image {}" , b64Image);
stream.close();
try {
out.flush();
} finally {
out.close();
}
}
}
public void setCaptchaProducer(Producer captchaProducer) {
this.captchaProducer = captchaProducer;
}
}
/* /*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,16 +18,24 @@ ...@@ -18,16 +18,24 @@
package org.maxkey.web.contorller; package org.maxkey.web.contorller;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
import com.nimbusds.jwt.JWTClaimsSet;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.ByteArrayOutputStream;
import java.util.Base64;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.entity.Message;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
...@@ -41,13 +49,15 @@ import org.springframework.web.bind.annotation.RequestParam; ...@@ -41,13 +49,15 @@ import org.springframework.web.bind.annotation.RequestParam;
@Controller @Controller
public class ImageCaptchaEndpoint { public class ImageCaptchaEndpoint {
private static final Logger _logger = LoggerFactory.getLogger(ImageCaptchaEndpoint.class); private static final Logger _logger = LoggerFactory.getLogger(ImageCaptchaEndpoint.class);
public static final String IMAGE_GIF = "image/gif";
public static final String KAPTCHA_SESSION_KEY = "kaptcha_session_key";
@Autowired @Autowired
private Producer captchaProducer; private Producer captchaProducer;
@Autowired
protected MomentaryService momentaryService;
@Autowired
AuthJwtService authJwtService;
/** /**
* captcha image Producer. * captcha image Producer.
...@@ -55,75 +65,55 @@ public class ImageCaptchaEndpoint { ...@@ -55,75 +65,55 @@ public class ImageCaptchaEndpoint {
* @param request HttpServletRequest * @param request HttpServletRequest
* @param response HttpServletResponse * @param response HttpServletResponse
*/ */
@RequestMapping(value = "/captcha") @RequestMapping(value={"/captcha"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public void captchaHandleRequest(HttpServletRequest request, public ResponseEntity<?> captchaHandleRequest(
HttpServletResponse response, @RequestParam(value="captcha",required=false,defaultValue="text") String captchaType,
@RequestParam(value="captcha",required=false,defaultValue="text") String captchaType) { @RequestParam(value="state",required=false,defaultValue="state") String state) {
try { try {
String kaptchaText = captchaProducer.createText(); String kaptchaText = captchaProducer.createText();
String kaptchaValue = kaptchaText;
if (captchaType.equalsIgnoreCase("Arithmetic")) { if (captchaType.equalsIgnoreCase("Arithmetic")) {
Integer intParamA = Integer.valueOf(kaptchaText.substring(0, 1)); Integer minuend = Integer.valueOf(kaptchaText.substring(0, 1));
Integer intParamB = Integer.valueOf(kaptchaText.substring(1, 2)); Integer subtrahend = Integer.valueOf(kaptchaText.substring(1, 2));
Integer calculateValue = 0; if (minuend - subtrahend > 0) {
if ((intParamA > intParamB) && ((intParamA + intParamB) % 5 > 3)) { kaptchaValue = (minuend - subtrahend ) + "";
calculateValue = intParamA - intParamB; kaptchaText = minuend + "-" + subtrahend + "=?";
kaptchaText = intParamA + "-" + intParamB + "=?";
} else { } else {
calculateValue = intParamA + intParamB; kaptchaValue = (minuend + subtrahend) + "";
kaptchaText = intParamA + "+" + intParamB + "=?"; kaptchaText = minuend + "+" + subtrahend + "=?";
} }
_logger.trace("Sesssion id " + request.getSession().getId()
+ " , Arithmetic calculate Value is " + calculateValue);
request.getSession().setAttribute(
KAPTCHA_SESSION_KEY, calculateValue + "");
} else {
// store the text in the session
request.getSession().setAttribute(KAPTCHA_SESSION_KEY, kaptchaText);
} }
_logger.trace("Sesssion id " + request.getSession().getId() String kaptchaKey = "";
+ " , Captcha Text is " + kaptchaText); if(StringUtils.isNotBlank(state)
&& !state.equalsIgnoreCase("state")
&& authJwtService.validateJwtToken(state)) {
JWTClaimsSet claim = authJwtService.resolve(state);
kaptchaKey = claim.getJWTID();
}else {
kaptchaKey = WebContext.genId();
}
_logger.trace("kaptchaKey {} , Captcha Text is {}" ,kaptchaKey, kaptchaValue);
momentaryService.put("", kaptchaKey, kaptchaValue);
// create the image with the text // create the image with the text
BufferedImage bufferedImage = captchaProducer.createImage(kaptchaText); BufferedImage bufferedImage = captchaProducer.createImage(kaptchaText);
producerImage(request,response,bufferedImage); // write the data out
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", stream);
String b64Image = "data:image/png;base64," +
Base64.getEncoder().encodeToString(stream.toByteArray());
_logger.trace("b64Image {}" , b64Image);
stream.close();
return new Message<ImageCaptcha>(
new ImageCaptcha(kaptchaKey,b64Image)
).buildResponse();
} catch (Exception e) { } catch (Exception e) {
_logger.error("captcha Producer Error " + e.getMessage()); _logger.error("captcha Producer Error " + e.getMessage());
} }
} return new Message< Object>(Message.FAIL).buildResponse();
/**
* producerImage.
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param bufferedImage BufferedImage
* @throws IOException error
*/
public static void producerImage(HttpServletRequest request,
HttpServletResponse response,
BufferedImage bufferedImage) throws IOException {
// Set to expire far in the past.
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg/gif
response.setContentType(IMAGE_GIF);
_logger.trace("create the image");
// create the image
if (bufferedImage != null) {
ServletOutputStream out = response.getOutputStream();
// write the data out
ImageIO.write(bufferedImage, "gif", out);
try {
out.flush();
} finally {
out.close();
}
}
} }
public void setCaptchaProducer(Producer captchaProducer) { public void setCaptchaProducer(Producer captchaProducer) {
......
kaptcha.image.width=80 kaptcha.image.width=80
kaptcha.image.height=40 kaptcha.image.height=40
kaptcha.border=no kaptcha.border=no
kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.ShadowGimpy #kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.ShadowGimpy
kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.Ripple
kaptcha.textproducer.font.size=23 kaptcha.textproducer.font.size=23
kaptcha.textproducer.char.string=0123456789 kaptcha.textproducer.char.string=0123456789
kaptcha.textproducer.char.length=4 kaptcha.textproducer.char.length=4
kaptcha.noise.impl=com.google.code.kaptcha.impl.NoNoise kaptcha.textproducer.char.space=3
#kaptcha.noise.color=white #kaptcha.noise.impl=com.google.code.kaptcha.impl.DefaultNoise
\ No newline at end of file kaptcha.noise.impl=com.google.code.kaptcha.impl.LightNoise
#kaptcha.noise.color=white
kaptcha.word.impl=com.google.code.kaptcha.text.impl.RandomColorWordRenderer
\ No newline at end of file
kaptcha.image.width=80
kaptcha.image.height=40
kaptcha.border=no
kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.ShadowGimpy
kaptcha.textproducer.font.size=23
kaptcha.textproducer.char.string=0123456789
kaptcha.textproducer.char.length=4
kaptcha.noise.impl=com.google.code.kaptcha.impl.NoNoise
#kaptcha.noise.color=white
\ No newline at end of file
...@@ -20,6 +20,7 @@ package org.maxkey.authn; ...@@ -20,6 +20,7 @@ package org.maxkey.authn;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.online.OnlineTicketService; import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm; import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.configuration.ApplicationConfig; import org.maxkey.configuration.ApplicationConfig;
...@@ -28,6 +29,7 @@ import org.maxkey.constants.ConstsStatus; ...@@ -28,6 +29,7 @@ import org.maxkey.constants.ConstsStatus;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn; import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.password.onetimepwd.OtpAuthnService; import org.maxkey.password.onetimepwd.OtpAuthnService;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.web.WebConstants; import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext; import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -51,7 +53,14 @@ public abstract class AbstractAuthenticationProvider { ...@@ -51,7 +53,14 @@ public abstract class AbstractAuthenticationProvider {
public final static String NORMAL = "normal"; public final static String NORMAL = "normal";
public final static String TFA = "tfa"; public final static String TFA = "tfa";
public final static String MOBILE = "mobile"; public final static String MOBILE = "mobile";
public final static String TRUSTED = "trusted";
} }
protected static String PROVIDER_SUFFIX = "AuthenticationProvider";
private static HashMap<String,AbstractAuthenticationProvider> providers =
new HashMap<String,AbstractAuthenticationProvider>();
protected ApplicationConfig applicationConfig; protected ApplicationConfig applicationConfig;
protected AbstractAuthenticationRealm authenticationRealm; protected AbstractAuthenticationRealm authenticationRealm;
...@@ -62,87 +71,42 @@ public abstract class AbstractAuthenticationProvider { ...@@ -62,87 +71,42 @@ public abstract class AbstractAuthenticationProvider {
protected OnlineTicketService onlineTicketServices; protected OnlineTicketService onlineTicketServices;
protected MomentaryService momentaryService;
protected AuthJwtService authJwtService;
public static ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>(); public static ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>();
static { static {
grantedAdministratorsAuthoritys.add(new SimpleGrantedAuthority("ROLE_ADMINISTRATORS")); grantedAdministratorsAuthoritys.add(new SimpleGrantedAuthority("ROLE_ADMINISTRATORS"));
} }
protected abstract String getProviderName(); public abstract String getProviderName();
public abstract Authentication authenticate(LoginCredential authentication); public abstract Authentication doAuthenticate(LoginCredential authentication);
public abstract Authentication authentication(LoginCredential loginCredential,boolean isTrusted);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public boolean supports(Class authentication) { public boolean supports(Class authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
} }
protected void changeSession(Authentication authentication) { public Authentication authenticate(LoginCredential authentication){
if(authentication.getAuthType().equalsIgnoreCase("trusted")) {
HashMap<String,Object> sessionAttributeMap = new HashMap<String,Object>(); return null;
for(String attributeName : WebContext.sessionAttributeNameList) { }
sessionAttributeMap.put(attributeName, WebContext.getAttribute(attributeName)); AbstractAuthenticationProvider provider = providers.get(authentication.getAuthType() + PROVIDER_SUFFIX);
WebContext.removeAttribute(attributeName);
} return provider == null ? null : provider.doAuthenticate(authentication);
//new Session
WebContext.getSession().invalidate();
for(String attributeName : WebContext.sessionAttributeNameList) {
WebContext.setAttribute(attributeName, sessionAttributeMap.get(attributeName));
}
} }
public Authentication authenticate(LoginCredential authentication,boolean trusted){
/** AbstractAuthenticationProvider provider = providers.get(AuthType.TRUSTED + PROVIDER_SUFFIX);
* session validate. return provider == null ? null : provider.doAuthenticate(authentication);
*
* @param sessionId String
*/
protected void sessionValid(String sessionId) {
if (sessionId == null || !sessionId.equals(WebContext.getSession().getId())) {
_logger.debug("login session valid error.");
_logger.debug("login session sessionId " + sessionId);
_logger.debug("login getSession sessionId " + WebContext.getSession().getId());
String message = WebContext.getI18nValue("login.error.session");
throw new BadCredentialsException(message);
}
}
/**
* session validate.
*
* @param jwtToken String
*/
protected void jwtTokenValid(String jwtToken) {
/*
* if(jwtToken!=null && ! jwtToken.equals("")){
* if(jwtLoginService.jwtTokenValidation(j_jwtToken)){ return; } }
*/
String message = WebContext.getI18nValue("login.error.session");
_logger.debug("login session valid error.");
throw new BadCredentialsException(message);
} }
protected void authTypeValid(String authType) { public void addAuthenticationProvider(AbstractAuthenticationProvider provider) {
_logger.debug("Login AuthN Type " + authType); providers.put(provider.getProviderName(), provider);
if (authType != null && (
authType.equalsIgnoreCase(AuthType.NORMAL)
|| authType.equalsIgnoreCase(AuthType.TFA)
|| authType.equalsIgnoreCase(AuthType.MOBILE)
)
) {
return;
}
final String message = WebContext.getI18nValue("login.error.authtype");
_logger.debug("Login AuthN type must eq basic or tfa , Error message is {}" , message);
throw new BadCredentialsException(message);
} }
/** /**
* captcha validate . * captcha validate .
* *
...@@ -189,28 +153,7 @@ public abstract class AbstractAuthenticationProvider { ...@@ -189,28 +153,7 @@ public abstract class AbstractAuthenticationProvider {
} }
} }
/**
* mobile validate.
*
* @param otpCaptcha String
* @param authType String
* @param userInfo UserInfo
*/
protected void mobilecaptchaValid(String password, String authType, UserInfo userInfo) {
// for mobile password
if (applicationConfig.getLoginConfig().isMfa()
&& authType.equalsIgnoreCase(AuthType.MOBILE)) {
UserInfo validUserInfo = new UserInfo();
validUserInfo.setUsername(userInfo.getUsername());
validUserInfo.setId(userInfo.getId());
AbstractOtpAuthn smsOtpAuthn = otpAuthnService.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);
}
}
}
/** /**
* login user by j_username and j_cname first query user by j_cname if first * login user by j_username and j_cname first query user by j_cname if first
......
...@@ -33,7 +33,7 @@ public class LoginCredential implements Authentication { ...@@ -33,7 +33,7 @@ public class LoginCredential implements Authentication {
String congress; String congress;
String username; String username;
String password; String password;
String sessionId; String state;
String captcha; String captcha;
String otpCaptcha; String otpCaptcha;
String remeberMe; String remeberMe;
...@@ -126,15 +126,15 @@ public class LoginCredential implements Authentication { ...@@ -126,15 +126,15 @@ public class LoginCredential implements Authentication {
this.password = password; this.password = password;
} }
public String getSessionId() { public String getState() {
return sessionId; return state;
} }
public void setSessionId(String sessionId) { public void setState(String state) {
this.sessionId = sessionId; this.state = state;
} }
public String getCaptcha() { public String getCaptcha() {
return captcha; return captcha;
} }
...@@ -233,12 +233,14 @@ public class LoginCredential implements Authentication { ...@@ -233,12 +233,14 @@ public class LoginCredential implements Authentication {
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("LoginCredential [username="); builder.append("LoginCredential [congress=");
builder.append(congress);
builder.append(", username=");
builder.append(username); builder.append(username);
builder.append(", password="); builder.append(", password=");
builder.append("******"); builder.append(password);
builder.append(", sessionId="); builder.append(", state=");
builder.append(sessionId); builder.append(state);
builder.append(", captcha="); builder.append(", captcha=");
builder.append(captcha); builder.append(captcha);
builder.append(", otpCaptcha="); builder.append(", otpCaptcha=");
......
...@@ -15,10 +15,14 @@ ...@@ -15,10 +15,14 @@
*/ */
package org.maxkey.authn; package org.maxkey.authn.provider;
import java.util.ArrayList; import java.util.ArrayList;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.SigninPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.online.OnlineTicket; import org.maxkey.authn.online.OnlineTicket;
import org.maxkey.authn.online.OnlineTicketService; import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm; import org.maxkey.authn.realm.AbstractAuthenticationRealm;
...@@ -27,13 +31,11 @@ import org.maxkey.configuration.ApplicationConfig; ...@@ -27,13 +31,11 @@ import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.constants.ConstsLoginType; import org.maxkey.constants.ConstsLoginType;
import org.maxkey.entity.Institutions; import org.maxkey.entity.Institutions;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn; import org.maxkey.persistence.MomentaryService;
import org.maxkey.password.onetimepwd.OtpAuthnService;
import org.maxkey.web.WebConstants; import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext; import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
...@@ -46,47 +48,40 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails; ...@@ -46,47 +48,40 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
* @author Crystal.Sea * @author Crystal.Sea
* *
*/ */
public class RealmAuthenticationProvider extends AbstractAuthenticationProvider { public class MfaAuthenticationProvider extends AbstractAuthenticationProvider {
private static final Logger _logger = private static final Logger _logger =
LoggerFactory.getLogger(RealmAuthenticationProvider.class); LoggerFactory.getLogger(MfaAuthenticationProvider.class);
protected String getProviderName() { public String getProviderName() {
return "RealmAuthenticationProvider"; return "normal" + PROVIDER_SUFFIX;
} }
public RealmAuthenticationProvider() { public MfaAuthenticationProvider() {
super(); super();
} }
public MfaAuthenticationProvider(
public RealmAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm, AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig, ApplicationConfig applicationConfig,
AbstractOtpAuthn tfaOtpAuthn, OnlineTicketService onlineTicketServices,
OtpAuthnService otpAuthnService, AuthJwtService authJwtService,
OnlineTicketService onlineTicketServices) { MomentaryService momentaryService) {
this.authenticationRealm = authenticationRealm; this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig; this.applicationConfig = applicationConfig;
this.tfaOtpAuthn = tfaOtpAuthn;
this.otpAuthnService = otpAuthnService;
this.onlineTicketServices = onlineTicketServices; this.onlineTicketServices = onlineTicketServices;
this.authJwtService = authJwtService;
this.momentaryService = momentaryService;
} }
@Override @Override
public Authentication authenticate(LoginCredential loginCredential) { public Authentication doAuthenticate(LoginCredential loginCredential) {
UsernamePasswordAuthenticationToken authenticationToken = null; UsernamePasswordAuthenticationToken authenticationToken = null;
_logger.debug("Trying to authenticate user '{}' via {}", _logger.debug("Trying to authenticate user '{}' via {}",
loginCredential.getPrincipal(), getProviderName()); loginCredential.getPrincipal(), getProviderName());
try { try {
_logger.debug("authentication " + loginCredential); _logger.debug("authentication " + loginCredential);
//sessionValid(loginCredential.getSessionId());
//jwtTokenValid(j_jwtToken);
authTypeValid(loginCredential.getAuthType());
Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST); Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
if(inst.getCaptchaSupport().equalsIgnoreCase("YES")) { if(inst.getCaptchaSupport().equalsIgnoreCase("YES")) {
...@@ -107,12 +102,10 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider ...@@ -107,12 +102,10 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
//Validate PasswordPolicy //Validate PasswordPolicy
authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo); authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo);
if(loginCredential.getAuthType().equalsIgnoreCase(AuthType.MOBILE)) {
mobilecaptchaValid(loginCredential.getPassword(),loginCredential.getAuthType(),userInfo); //Match password
}else { authenticationRealm.passwordMatches(userInfo, loginCredential.getPassword());
//Match password
authenticationRealm.passwordMatches(userInfo, loginCredential.getPassword());
}
//apply PasswordSetType and resetBadPasswordCount //apply PasswordSetType and resetBadPasswordCount
authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo); authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
...@@ -121,8 +114,6 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider ...@@ -121,8 +114,6 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
_logger.debug("'{}' authenticated successfully by {}.", _logger.debug("'{}' authenticated successfully by {}.",
loginCredential.getPrincipal(), getProviderName()); loginCredential.getPrincipal(), getProviderName());
changeSession(authenticationToken);
authenticationRealm.insertLoginHistory(userInfo, authenticationRealm.insertLoginHistory(userInfo,
ConstsLoginType.LOCAL, ConstsLoginType.LOCAL,
"", "",
...@@ -143,46 +134,6 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider ...@@ -143,46 +134,6 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
return authenticationToken; return authenticationToken;
} }
/**
* trustAuthentication.
* @param username String
* @param type String
* @param provider String
* @param code String
* @param message String
* @return boolean
*/
@Override
public Authentication authentication(LoginCredential loginCredential,boolean isTrusted) {
UserInfo loadeduserInfo = loadUserInfo(loginCredential.getUsername(), "");
statusValid(loginCredential , loadeduserInfo);
if (loadeduserInfo != null) {
//Validate PasswordPolicy
authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(loadeduserInfo);
if(!isTrusted) {
authenticationRealm.passwordMatches(loadeduserInfo, loginCredential.getPassword());
}
//apply PasswordSetType and resetBadPasswordCount
authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(loadeduserInfo);
Authentication authentication = createOnlineSession(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"));
}
}
public UsernamePasswordAuthenticationToken createOnlineSession(LoginCredential credential,UserInfo userInfo) { public UsernamePasswordAuthenticationToken createOnlineSession(LoginCredential credential,UserInfo userInfo) {
//Online Tickit //Online Tickit
OnlineTicket onlineTicket = new OnlineTicket(); OnlineTicket onlineTicket = new OnlineTicket();
......
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.provider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.constants.ConstsLoginType;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.password.onetimepwd.OtpAuthnService;
import org.maxkey.web.WebConstants;
import org.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 NormalAuthenticationProvider {
private static final Logger _logger =
LoggerFactory.getLogger(MobileAuthenticationProvider.class);
public String getProviderName() {
return "mobile" + PROVIDER_SUFFIX;
}
public MobileAuthenticationProvider() {
super();
}
public MobileAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
OtpAuthnService otpAuthnService,
OnlineTicketService onlineTicketServices) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.otpAuthnService = otpAuthnService;
this.onlineTicketServices = onlineTicketServices;
}
@Override
public Authentication authenticate(LoginCredential loginCredential) {
UsernamePasswordAuthenticationToken authenticationToken = null;
_logger.debug("Trying to authenticate user '{}' via {}",
loginCredential.getPrincipal(), getProviderName());
try {
_logger.debug("authentication " + loginCredential);
emptyPasswordValid(loginCredential.getPassword());
emptyUsernameValid(loginCredential.getUsername());
UserInfo userInfo = loadUserInfo(loginCredential.getUsername(),loginCredential.getPassword());
statusValid(loginCredential , userInfo);
//Validate PasswordPolicy
authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo);
mobilecaptchaValid(loginCredential.getPassword(),userInfo);
//apply PasswordSetType and resetBadPasswordCount
authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
authenticationToken = createOnlineSession(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 = otpAuthnService.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);
}
}
}
}
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.provider;
import java.util.ArrayList;
import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.SigninPrincipal;
import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.online.OnlineTicket;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.web.AuthorizationUtils;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.constants.ConstsLoginType;
import org.maxkey.entity.Institutions;
import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
/**
* database Authentication provider.
* @author Crystal.Sea
*
*/
public class NormalAuthenticationProvider extends AbstractAuthenticationProvider {
private static final Logger _logger =
LoggerFactory.getLogger(NormalAuthenticationProvider.class);
public String getProviderName() {
return "normal" + PROVIDER_SUFFIX;
}
public NormalAuthenticationProvider() {
super();
}
public NormalAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
OnlineTicketService onlineTicketServices,
AuthJwtService authJwtService,
MomentaryService momentaryService) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.onlineTicketServices = onlineTicketServices;
this.authJwtService = authJwtService;
this.momentaryService = momentaryService;
}
@Override
public Authentication doAuthenticate(LoginCredential loginCredential) {
UsernamePasswordAuthenticationToken authenticationToken = null;
_logger.debug("Trying to authenticate user '{}' via {}",
loginCredential.getPrincipal(), getProviderName());
try {
_logger.debug("authentication " + loginCredential);
Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
if(inst.getCaptchaSupport().equalsIgnoreCase("YES")) {
captchaValid(loginCredential.getCaptcha(),loginCredential.getAuthType());
}
emptyPasswordValid(loginCredential.getPassword());
emptyUsernameValid(loginCredential.getUsername());
UserInfo userInfo = loadUserInfo(loginCredential.getUsername(),loginCredential.getPassword());
statusValid(loginCredential , userInfo);
//Validate PasswordPolicy
authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo);
//Match password
authenticationRealm.passwordMatches(userInfo, loginCredential.getPassword());
//apply PasswordSetType and resetBadPasswordCount
authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
authenticationToken = createOnlineSession(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;
}
public UsernamePasswordAuthenticationToken createOnlineSession(LoginCredential credential,UserInfo userInfo) {
//Online Tickit
OnlineTicket onlineTicket = new OnlineTicket();
userInfo.setOnlineTicket(onlineTicket.getTicketId());
SigninPrincipal principal = new SigninPrincipal(userInfo);
//set OnlineTicket
principal.setOnlineTicket(onlineTicket);
ArrayList<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()));
onlineTicket.setAuthentication(authenticationToken);
//store onlineTicket
this.onlineTicketServices.store(onlineTicket.getTicketId(), onlineTicket);
/*
* put Authentication to current session context
*/
AuthorizationUtils.setAuthentication(authenticationToken);
return authenticationToken;
}
}
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.provider;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.entity.UserInfo;
import org.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 NormalAuthenticationProvider {
private static final Logger _logger =
LoggerFactory.getLogger(TrustedAuthenticationProvider.class);
public String getProviderName() {
return "trusted" + PROVIDER_SUFFIX;
}
public TrustedAuthenticationProvider() {
super();
}
public TrustedAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
OnlineTicketService onlineTicketServices) {
this.authenticationRealm = authenticationRealm;
this.applicationConfig = applicationConfig;
this.onlineTicketServices = onlineTicketServices;
}
@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 = createOnlineSession(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"));
}
}
}
...@@ -131,7 +131,7 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor { ...@@ -131,7 +131,7 @@ public class BasicEntryPoint implements AsyncHandlerInterceptor {
if(!isAuthenticated){ if(!isAuthenticated){
LoginCredential loginCredential =new LoginCredential(headerCredential.getUsername(),"",ConstsLoginType.BASIC); LoginCredential loginCredential =new LoginCredential(headerCredential.getUsername(),"",ConstsLoginType.BASIC);
authenticationProvider.authentication(loginCredential,true); authenticationProvider.authenticate(loginCredential,true);
_logger.info("Authentication "+headerCredential.getUsername()+" successful ."); _logger.info("Authentication "+headerCredential.getUsername()+" successful .");
} }
......
...@@ -110,7 +110,7 @@ public class HttpHeaderEntryPoint implements AsyncHandlerInterceptor { ...@@ -110,7 +110,7 @@ public class HttpHeaderEntryPoint implements AsyncHandlerInterceptor {
if(!isAuthenticated){ if(!isAuthenticated){
LoginCredential loginCredential =new LoginCredential(httpHeaderUsername,"",ConstsLoginType.HTTPHEADER); LoginCredential loginCredential =new LoginCredential(httpHeaderUsername,"",ConstsLoginType.HTTPHEADER);
authenticationProvider.authentication(loginCredential,true); authenticationProvider.authenticate(loginCredential,true);
_logger.info("Authentication "+httpHeaderUsername+" successful ."); _logger.info("Authentication "+httpHeaderUsername+" successful .");
} }
......
...@@ -79,7 +79,7 @@ public class HttpJwtEntryPoint implements AsyncHandlerInterceptor { ...@@ -79,7 +79,7 @@ public class HttpJwtEntryPoint implements AsyncHandlerInterceptor {
if(signedJWT != null) { if(signedJWT != null) {
String username =signedJWT.getJWTClaimsSet().getSubject(); String username =signedJWT.getJWTClaimsSet().getSubject();
LoginCredential loginCredential =new LoginCredential(username,"",ConstsLoginType.JWT); LoginCredential loginCredential =new LoginCredential(username,"",ConstsLoginType.JWT);
authenticationProvider.authentication(loginCredential,true); authenticationProvider.authenticate(loginCredential,true);
_logger.debug("JWT Logined in , username " + username); _logger.debug("JWT Logined in , username " + username);
} }
......
...@@ -97,7 +97,7 @@ public class HttpKerberosEntryPoint implements AsyncHandlerInterceptor { ...@@ -97,7 +97,7 @@ public class HttpKerberosEntryPoint implements AsyncHandlerInterceptor {
if(notOnOrAfter.isAfterNow()){ if(notOnOrAfter.isAfterNow()){
LoginCredential loginCredential =new LoginCredential(kerberosToken.getPrincipal(),"",ConstsLoginType.KERBEROS); LoginCredential loginCredential =new LoginCredential(kerberosToken.getPrincipal(),"",ConstsLoginType.KERBEROS);
loginCredential.setProvider(kerberosUserDomain); loginCredential.setProvider(kerberosUserDomain);
authenticationProvider.authentication(loginCredential,true); authenticationProvider.authenticate(loginCredential,true);
_logger.debug("Kerberos Logined in , username " + kerberosToken.getPrincipal()); _logger.debug("Kerberos Logined in , username " + kerberosToken.getPrincipal());
} }
......
...@@ -100,7 +100,7 @@ public class HttpWsFederationEntryPoint implements AsyncHandlerInterceptor { ...@@ -100,7 +100,7 @@ public class HttpWsFederationEntryPoint implements AsyncHandlerInterceptor {
} }
LoginCredential loginCredential =new LoginCredential( LoginCredential loginCredential =new LoginCredential(
wsFederationCredential.getAttributes().get("").toString(),"",ConstsLoginType.WSFEDERATION); wsFederationCredential.getAttributes().get("").toString(),"",ConstsLoginType.WSFEDERATION);
authenticationProvider.authentication(loginCredential,true); authenticationProvider.authenticate(loginCredential,true);
return true; return true;
} else { } else {
_logger.warn("SAML assertions are blank or no longer valid."); _logger.warn("SAML assertions are blank or no longer valid.");
......
/* /*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
package org.maxkey.autoconfigure; package org.maxkey.autoconfigure;
import org.maxkey.authn.AbstractAuthenticationProvider; import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.RealmAuthenticationProvider;
import org.maxkey.authn.SavedRequestAwareAuthenticationSuccessHandler; import org.maxkey.authn.SavedRequestAwareAuthenticationSuccessHandler;
import org.maxkey.authn.jwt.AuthJwtService; import org.maxkey.authn.jwt.AuthJwtService;
import org.maxkey.authn.jwt.CongressService; import org.maxkey.authn.jwt.CongressService;
...@@ -26,6 +25,9 @@ import org.maxkey.authn.jwt.InMemoryCongressService; ...@@ -26,6 +25,9 @@ import org.maxkey.authn.jwt.InMemoryCongressService;
import org.maxkey.authn.jwt.RedisCongressService; import org.maxkey.authn.jwt.RedisCongressService;
import org.maxkey.authn.online.OnlineTicketService; import org.maxkey.authn.online.OnlineTicketService;
import org.maxkey.authn.online.OnlineTicketServiceFactory; import org.maxkey.authn.online.OnlineTicketServiceFactory;
import org.maxkey.authn.provider.MobileAuthenticationProvider;
import org.maxkey.authn.provider.NormalAuthenticationProvider;
import org.maxkey.authn.provider.TrustedAuthenticationProvider;
import org.maxkey.authn.realm.AbstractAuthenticationRealm; import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.web.SessionListenerAdapter; import org.maxkey.authn.web.SessionListenerAdapter;
import org.maxkey.configuration.ApplicationConfig; import org.maxkey.configuration.ApplicationConfig;
...@@ -34,6 +36,7 @@ import org.maxkey.constants.ConstsPersistence; ...@@ -34,6 +36,7 @@ import org.maxkey.constants.ConstsPersistence;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn; import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.password.onetimepwd.OtpAuthnService; import org.maxkey.password.onetimepwd.OtpAuthnService;
import org.maxkey.password.onetimepwd.token.RedisOtpTokenStore; import org.maxkey.password.onetimepwd.token.RedisOtpTokenStore;
import org.maxkey.persistence.MomentaryService;
import org.maxkey.persistence.redis.RedisConnectionFactory; import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.maxkey.persistence.repository.LoginHistoryRepository; import org.maxkey.persistence.repository.LoginHistoryRepository;
import org.maxkey.persistence.repository.LoginRepository; import org.maxkey.persistence.repository.LoginRepository;
...@@ -68,20 +71,61 @@ public class AuthenticationAutoConfiguration implements InitializingBean { ...@@ -68,20 +71,61 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
public AbstractAuthenticationProvider authenticationProvider( public AbstractAuthenticationProvider authenticationProvider(
AbstractAuthenticationRealm authenticationRealm, AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig, ApplicationConfig applicationConfig,
AbstractOtpAuthn tfaOtpAuthn, OnlineTicketService onlineTicketServices,
OtpAuthnService otpAuthnService, AuthJwtService authJwtService,
OnlineTicketService onlineTicketServices MomentaryService momentaryService
) { ) {
_logger.debug("init authentication Provider ."); _logger.debug("init authentication Provider .");
return new RealmAuthenticationProvider( NormalAuthenticationProvider normal = new NormalAuthenticationProvider(
authenticationRealm,
applicationConfig,
onlineTicketServices,
authJwtService,
momentaryService
);
normal.addAuthenticationProvider(normal);
return normal;
}
@Bean(name = "mobileAuthenticationProvider")
public AbstractAuthenticationProvider mobileAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
OtpAuthnService otpAuthnService,
OnlineTicketService onlineTicketServices,
AbstractAuthenticationProvider authenticationProvider
) {
MobileAuthenticationProvider mobile = new MobileAuthenticationProvider(
authenticationRealm, authenticationRealm,
applicationConfig, applicationConfig,
tfaOtpAuthn,
otpAuthnService, otpAuthnService,
onlineTicketServices onlineTicketServices
); );
authenticationProvider.addAuthenticationProvider(mobile);
_logger.debug("init Mobile authentication Provider .");
return mobile;
}
@Bean(name = "trustedAuthenticationProvider")
public AbstractAuthenticationProvider trustedAuthenticationProvider(
AbstractAuthenticationRealm authenticationRealm,
ApplicationConfig applicationConfig,
OnlineTicketService onlineTicketServices,
AbstractAuthenticationProvider authenticationProvider
) {
TrustedAuthenticationProvider trusted = new TrustedAuthenticationProvider(
authenticationRealm,
applicationConfig,
onlineTicketServices
);
authenticationProvider.addAuthenticationProvider(trusted);
_logger.debug("init Mobile authentication Provider .");
return trusted;
} }
@Bean(name = "authJwtService") @Bean(name = "authJwtService")
......
...@@ -133,7 +133,7 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint{ ...@@ -133,7 +133,7 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint{
SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider); SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
loginCredential.setProvider(socialSignOnProvider.getProviderName()); loginCredential.setProvider(socialSignOnProvider.getProviderName());
Authentication authentication = authenticationProvider.authentication(loginCredential,true); Authentication authentication = authenticationProvider.authenticate(loginCredential,true);
//socialsAssociate.setAccessToken(JsonUtils.object2Json(this.accessToken)); //socialsAssociate.setAccessToken(JsonUtils.object2Json(this.accessToken));
socialsAssociate.setSocialUserInfo(accountJsonString); socialsAssociate.setSocialUserInfo(accountJsonString);
//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject())); //socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
......
...@@ -30,7 +30,7 @@ public class InMemoryMomentaryService implements MomentaryService{ ...@@ -30,7 +30,7 @@ public class InMemoryMomentaryService implements MomentaryService{
protected static Cache<String, Object> momentaryStore = protected static Cache<String, Object> momentaryStore =
Caffeine.newBuilder() Caffeine.newBuilder()
.expireAfterWrite(3, TimeUnit.MINUTES) .expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(200000) .maximumSize(200000)
.build(); .build();
......
...@@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory; ...@@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory;
public class RedisMomentaryService implements MomentaryService { public class RedisMomentaryService implements MomentaryService {
private static final Logger _logger = LoggerFactory.getLogger(RedisMomentaryService.class); private static final Logger _logger = LoggerFactory.getLogger(RedisMomentaryService.class);
protected int validitySeconds = 60 * 3; //default 3 minutes. protected int validitySeconds = 60 * 5; //default 5 minutes.
RedisConnectionFactory connectionFactory; RedisConnectionFactory connectionFactory;
......
...@@ -83,7 +83,7 @@ public class CasRestV1Endpoint extends CasBaseAuthorizeEndpoint{ ...@@ -83,7 +83,7 @@ public class CasRestV1Endpoint extends CasBaseAuthorizeEndpoint{
LoginCredential loginCredential =new LoginCredential(username,password,"CASREST"); LoginCredential loginCredential =new LoginCredential(username,password,"CASREST");
authenticationProvider.authentication(loginCredential,false); authenticationProvider.authenticate(loginCredential,false);
TicketGrantingTicketImpl ticketGrantingTicket=new TicketGrantingTicketImpl("Random",AuthorizationUtils.getAuthentication(),null); TicketGrantingTicketImpl ticketGrantingTicket=new TicketGrantingTicketImpl("Random",AuthorizationUtils.getAuthentication(),null);
...@@ -187,7 +187,7 @@ public class CasRestV1Endpoint extends CasBaseAuthorizeEndpoint{ ...@@ -187,7 +187,7 @@ public class CasRestV1Endpoint extends CasBaseAuthorizeEndpoint{
LoginCredential loginCredential =new LoginCredential(username,password,"CASREST"); LoginCredential loginCredential =new LoginCredential(username,password,"CASREST");
authenticationProvider.authentication(loginCredential,false); authenticationProvider.authenticate(loginCredential,false);
UserInfo userInfo = AuthorizationUtils.getUserInfo(); UserInfo userInfo = AuthorizationUtils.getUserInfo();
TicketGrantingTicketImpl ticketGrantingTicket=new TicketGrantingTicketImpl("Random",AuthorizationUtils.getAuthentication(),null); TicketGrantingTicketImpl ticketGrantingTicket=new TicketGrantingTicketImpl("Random",AuthorizationUtils.getAuthentication(),null);
......
...@@ -195,7 +195,7 @@ public class ConsumerEndpoint { ...@@ -195,7 +195,7 @@ public class ConsumerEndpoint {
LoginCredential loginCredential =new LoginCredential( LoginCredential loginCredential =new LoginCredential(
username,"",ConstsLoginType.SAMLTRUST); username,"",ConstsLoginType.SAMLTRUST);
Authentication authentication = authenticationProvider.authentication(loginCredential,true); Authentication authentication = authenticationProvider.authenticate(loginCredential,true);
if(authentication == null) { if(authentication == null) {
String congress = authJwtService.createCongress(authentication); String congress = authJwtService.createCongress(authentication);
} }
......
...@@ -71,7 +71,7 @@ public class LoginEntryPoint { ...@@ -71,7 +71,7 @@ public class LoginEntryPoint {
@Autowired @Autowired
@Qualifier("authenticationProvider") @Qualifier("authenticationProvider")
AbstractAuthenticationProvider authenticationProvider ; AbstractAuthenticationProvider authenticationProvider ;
@Autowired @Autowired
@Qualifier("socialSignOnProviderService") @Qualifier("socialSignOnProviderService")
SocialSignOnProviderService socialSignOnProviderService; SocialSignOnProviderService socialSignOnProviderService;
...@@ -146,12 +146,20 @@ public class LoginEntryPoint { ...@@ -146,12 +146,20 @@ public class LoginEntryPoint {
*/ */
@RequestMapping(value={"/signin"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/signin"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> signin( @RequestBody LoginCredential loginCredential) { public ResponseEntity<?> signin( @RequestBody LoginCredential loginCredential) {
Message<AuthJwt> authJwtMessage = new Message<AuthJwt>(Message.FAIL);
Authentication authentication = authenticationProvider.authenticate(loginCredential); if(authJwtService.validateJwtToken(loginCredential.getState())){
if(authentication == null) { String authType = loginCredential.getAuthType();
return new Message<AuthJwt>(Message.FAIL).buildResponse(); _logger.debug("Login AuthN Type " + authType);
if (StringUtils.isNotBlank(authType)){
Authentication authentication = authenticationProvider.doAuthenticate(loginCredential);
if(authentication != null) {
authJwtMessage = new Message<AuthJwt>(authJwtService.genAuthJwt(authentication));
}
}else {
_logger.error("Login AuthN type must eq normal , tfa or mobile . ");
}
} }
return new Message<AuthJwt>(authJwtService.genAuthJwt(authentication)).buildResponse(); return authJwtMessage.buildResponse();
} }
/** /**
......
/* /*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
package org.maxkey.web.contorller; package org.maxkey.web.contorller;
import java.util.HashMap;
import org.maxkey.authn.AbstractAuthenticationProvider; import org.maxkey.authn.AbstractAuthenticationProvider;
import org.maxkey.authn.LoginCredential; import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.jwt.AuthJwt; import org.maxkey.authn.jwt.AuthJwt;
...@@ -35,7 +37,6 @@ import org.springframework.security.core.Authentication; ...@@ -35,7 +37,6 @@ import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
...@@ -48,14 +49,11 @@ public class LoginEntryPoint { ...@@ -48,14 +49,11 @@ public class LoginEntryPoint {
private static Logger _logger = LoggerFactory.getLogger(LoginEntryPoint.class); private static Logger _logger = LoggerFactory.getLogger(LoginEntryPoint.class);
@Autowired @Autowired
@Qualifier("authJwtService")
AuthJwtService authJwtService; AuthJwtService authJwtService;
@Autowired @Autowired
@Qualifier("applicationConfig")
protected ApplicationConfig applicationConfig; protected ApplicationConfig applicationConfig;
@Autowired @Autowired
@Qualifier("authenticationProvider") @Qualifier("authenticationProvider")
AbstractAuthenticationProvider authenticationProvider ; AbstractAuthenticationProvider authenticationProvider ;
...@@ -64,34 +62,28 @@ public class LoginEntryPoint { ...@@ -64,34 +62,28 @@ public class LoginEntryPoint {
* init login * init login
* @return * @return
*/ */
@RequestMapping(value={"/login"}) @RequestMapping(value={"/get"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ModelAndView login() { public ResponseEntity<?> get() {
_logger.debug("LoginController /login."); _logger.debug("LoginController /login.");
boolean isAuthenticated= false;//WebContext.isAuthenticated(); HashMap<String , Object> model = new HashMap<String , Object>();
//for normal login model.put("isRemeberMe", applicationConfig.getLoginConfig().isRemeberMe());
if(isAuthenticated){
return WebContext.redirect("/main");
}
ModelAndView modelAndView = new ModelAndView();
Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST); Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
modelAndView.addObject("isRemeberMe", applicationConfig.getLoginConfig().isRemeberMe()); model.put("inst", inst);
modelAndView.addObject("captchaSupport", inst.getCaptchaSupport()); model.put("captcha", inst.getCaptchaSupport());
modelAndView.addObject("captchaType", inst.getCaptchaType()); model.put("captchaType", inst.getCaptchaType());
modelAndView.addObject("sessionid", WebContext.getSession().getId()); model.put("state", authJwtService.genJwt());
Object loginErrorMessage=WebContext.getAttribute(WebConstants.LOGIN_ERROR_SESSION_MESSAGE); return new Message<HashMap<String , Object>>(model).buildResponse();
modelAndView.addObject("loginErrorMessage", loginErrorMessage==null?"":loginErrorMessage);
WebContext.removeAttribute(WebConstants.LOGIN_ERROR_SESSION_MESSAGE);
modelAndView.setViewName("login");
return modelAndView;
} }
@RequestMapping(value={"/signin"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/signin"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> signin( @RequestBody LoginCredential loginCredential) { public ResponseEntity<?> signin( @RequestBody LoginCredential loginCredential) {
Authentication authentication = authenticationProvider.authenticate(loginCredential); if(authJwtService.validateJwtToken(loginCredential.getState())){
AuthJwt authJwt = authJwtService.genAuthJwt(authentication); Authentication authentication = authenticationProvider.authenticate(loginCredential);
return new Message<AuthJwt>(authJwt).buildResponse(); AuthJwt authJwt = authJwtService.genAuthJwt(authentication);
return new Message<AuthJwt>(authJwt).buildResponse();
}
return new Message<AuthJwt>(Message.FAIL).buildResponse();
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册