优化

master
smallbun 2024-12-16 01:06:32 +08:00
parent 9c135e74f3
commit 9be0add496
65 changed files with 533 additions and 251 deletions

View File

@ -36,7 +36,7 @@ import cn.topiam.employee.audit.entity.*;
import cn.topiam.employee.audit.enums.EventStatus;
import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.support.context.ServletContextService;
import cn.topiam.employee.support.geo.GeoLocationService;
import cn.topiam.employee.support.geo.GeoLocationParser;
import cn.topiam.employee.support.security.authentication.WebAuthenticationDetails;
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.security.userdetails.UserType;
@ -272,7 +272,7 @@ public class AuditEventPublish {
private UserAgent getUserAgent() {
//@formatter:off
HttpServletRequest request = ServletContextService.getRequest();
cn.topiam.employee.support.web.useragent.UserAgent ua = UserAgentParser.getUserAgent(request);
cn.topiam.employee.support.web.useragent.UserAgent ua = userAgentParser.getUserAgent(request);
return UserAgent.builder()
.browser(ua.getBrowser())
.browserType(ua.getBrowserType())
@ -293,7 +293,7 @@ public class AuditEventPublish {
//@formatter:off
HttpServletRequest request = ServletContextService.getRequest();
String ip = IpUtils.getIpAddr(request);
cn.topiam.employee.support.geo.GeoLocation geoLocation = geoLocationService.getGeoLocation(ip);
cn.topiam.employee.support.geo.GeoLocation geoLocation = geoLocationParser.getGeoLocation(ip);
if (Objects.isNull(geoLocation)){
return null;
}
@ -386,11 +386,17 @@ public class AuditEventPublish {
/**
*
*/
private final GeoLocationService geoLocationService;
private final GeoLocationParser geoLocationParser;
/**
* UserAgentParser
*/
private final UserAgentParser userAgentParser;
public AuditEventPublish(ApplicationEventPublisher applicationEventPublisher,
GeoLocationService geoLocationService) {
GeoLocationParser geoLocationParser, UserAgentParser userAgentParser) {
this.applicationEventPublisher = applicationEventPublisher;
this.geoLocationService = geoLocationService;
this.geoLocationParser = geoLocationParser;
this.userAgentParser = userAgentParser;
}
}

View File

@ -18,11 +18,11 @@
package cn.topiam.employee.authentication.common.template;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.compress.utils.CharsetNames;
import org.apache.http.entity.ContentType;
import org.springframework.http.HttpStatus;
@ -60,7 +60,7 @@ public class BindIdentityProviderTemplate {
ApiRestResult<Void> result) throws IOException {
//@formatter:off
try {
response.setCharacterEncoding(CharsetNames.UTF_8);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType(ContentType.TEXT_HTML.getMimeType());
Template template = freemarkerTemplateConfiguration.getTemplate("bind_redirect.ftlh");
Map<String, Object> data = new HashMap<>(16);
@ -82,7 +82,7 @@ public class BindIdentityProviderTemplate {
freemarkerTemplateConfiguration
.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/template/"));
//编码
freemarkerTemplateConfiguration.setDefaultEncoding(CharsetNames.UTF_8);
freemarkerTemplateConfiguration.setDefaultEncoding(StandardCharsets.UTF_8.name());
//国际化
freemarkerTemplateConfiguration.setLocale(new Locale("zh_CN"));
} catch (Exception exception) {

View File

@ -36,7 +36,7 @@ import cn.topiam.employee.common.repository.account.UserRepository;
import cn.topiam.employee.core.security.otp.OtpContextHelp;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.util.PhoneUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
@ -44,7 +44,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import static cn.topiam.employee.common.enums.MessageNoticeChannel.SMS;
import static cn.topiam.employee.support.security.constant.SecurityConstants.LOGIN_PATH;
import static cn.topiam.employee.support.util.PhoneNumberUtils.isPhoneValidate;
import static cn.topiam.employee.support.util.PhoneUtils.isPhoneValidate;
/**
* OTP
@ -85,7 +85,7 @@ public class SendSmsOtpFilter extends OncePerRequestFilter {
if (isPhoneValidate(recipient)) {
//判断是否存在用户
Optional<UserEntity> user = userRepository
.findByPhone(PhoneNumberUtils.getPhoneNumber(recipient));
.findByPhone(PhoneUtils.getPhoneNumber(recipient));
if (user.isPresent()) {
otpContextHelp.sendOtp(recipient, SmsType.LOGIN.getCode(), SMS);
HttpResponseUtils.flushResponseJson(response, HttpStatus.OK.value(),

View File

@ -27,6 +27,7 @@ import org.springframework.security.core.AuthenticationException;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.security.web.AbstractAuthenticationEntryPoint;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@ -71,4 +72,8 @@ public class ConsoleAuthenticationEntryPoint extends AbstractAuthenticationEntry
.build();
HttpResponseUtils.flushResponseJson(response, UNAUTHORIZED.value(), result);
}
public ConsoleAuthenticationEntryPoint(UserAgentParser userAgentParser) {
super(userAgentParser);
}
}

View File

@ -22,7 +22,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import cn.topiam.employee.EiamConsoleApplication;
import cn.topiam.employee.support.util.AppVersionUtils;
import cn.topiam.employee.support.util.VersionUtils;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
@ -59,7 +59,7 @@ public class ConsoleApiConfiguration {
//内容
.contact(contact)
//版本
.version(AppVersionUtils.getVersion(EiamConsoleApplication.class));
.version(VersionUtils.getVersion(EiamConsoleApplication.class));
}
/**

View File

@ -58,11 +58,12 @@ import cn.topiam.employee.common.entity.setting.SettingEntity;
import cn.topiam.employee.common.repository.setting.AdministratorRepository;
import cn.topiam.employee.common.repository.setting.SettingRepository;
import cn.topiam.employee.console.authentication.*;
import cn.topiam.employee.support.geo.GeoLocationService;
import cn.topiam.employee.support.geo.GeoLocationParser;
import cn.topiam.employee.support.jackjson.SupportJackson2Module;
import cn.topiam.employee.support.security.authentication.WebAuthenticationDetailsSource;
import cn.topiam.employee.support.security.configurer.FormLoginConfigurer;
import cn.topiam.employee.support.security.csrf.SpaCsrfTokenRequestHandler;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import lombok.RequiredArgsConstructor;
import static org.springframework.security.config.Customizer.withDefaults;
@ -247,7 +248,8 @@ public class ConsoleSecurityConfiguration implements BeanClassLoaderAware {
*/
public Customizer<ExceptionHandlingConfigurer<HttpSecurity>> withExceptionConfigurerDefaults() {
return configurer -> {
configurer.authenticationEntryPoint(new ConsoleAuthenticationEntryPoint());
configurer
.authenticationEntryPoint(new ConsoleAuthenticationEntryPoint(userAgentParser));
configurer.accessDeniedHandler(new ConsoleAccessDeniedHandler());
configurer
.withObjectPostProcessor(new ObjectPostProcessor<ExceptionTranslationFilter>() {
@ -353,12 +355,13 @@ public class ConsoleSecurityConfiguration implements BeanClassLoaderAware {
/**
* WebAuthenticationDetailsSource
*
* @param geoLocationService {@link GeoLocationService}
* @param geoLocationParser {@link GeoLocationParser}
* @return {@link WebAuthenticationDetailsSource}
*/
@Bean
public WebAuthenticationDetailsSource authenticationDetailsSource(GeoLocationService geoLocationService) {
return new WebAuthenticationDetailsSource(geoLocationService);
public WebAuthenticationDetailsSource authenticationDetailsSource(GeoLocationParser geoLocationParser,
UserAgentParser userAgentParser) {
return new WebAuthenticationDetailsSource(geoLocationParser, userAgentParser);
}
private ClassLoader loader;
@ -383,4 +386,9 @@ public class ConsoleSecurityConfiguration implements BeanClassLoaderAware {
*/
private final AuditEventPublish auditEventPublish;
/**
* UserAgentParser
*/
private final UserAgentParser userAgentParser;
}

View File

@ -32,15 +32,16 @@ import cn.topiam.employee.common.exception.UserNotFoundException;
import cn.topiam.employee.common.repository.setting.AdministratorRepository;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.util.DesensitizationUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.oas.annotations.media.Schema;
import static cn.topiam.employee.common.constant.SessionConstants.CURRENT_USER;
import static cn.topiam.employee.support.util.ImageAvatarUtils.bufferedImageToBase64;
import static cn.topiam.employee.support.util.ImageAvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.AvatarUtils.bufferedImageToBase64;
import static cn.topiam.employee.support.util.AvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.DesensitizationUtils.emailEncrypt;
import static cn.topiam.employee.support.util.DesensitizationUtils.phoneEncrypt;
/**
*
@ -81,9 +82,9 @@ public class CurrentUserEndpoint {
result.setAvatar(administrator.getAvatar());
}
//邮箱
result.setEmail(DesensitizationUtil.emailEncrypt(administrator.getEmail()));
result.setEmail(emailEncrypt(administrator.getEmail()));
//手机号
result.setPhone(DesensitizationUtil.phoneEncrypt(administrator.getPhone()));
result.setPhone(phoneEncrypt(administrator.getPhone()));
return ApiRestResult.ok(result);
}

View File

@ -31,8 +31,8 @@ import cn.topiam.employee.console.pojo.result.account.*;
import cn.topiam.employee.console.pojo.save.account.OrganizationCreateParam;
import cn.topiam.employee.console.pojo.update.account.OrganizationUpdateParam;
import cn.topiam.employee.console.service.account.OrganizationService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import io.swagger.v3.oas.annotations.Operation;

View File

@ -41,8 +41,8 @@ import cn.topiam.employee.console.pojo.update.account.UserUpdateParam;
import cn.topiam.employee.console.service.account.UserService;
import cn.topiam.employee.console.service.app.UserIdpBindService;
import cn.topiam.employee.core.security.otp.OtpContextHelp;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -38,8 +38,8 @@ import cn.topiam.employee.console.pojo.save.account.UserCreateParam;
import cn.topiam.employee.console.pojo.save.account.UserGroupCreateParam;
import cn.topiam.employee.console.pojo.update.account.UserGroupUpdateParam;
import cn.topiam.employee.console.service.account.UserGroupService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -29,8 +29,8 @@ import cn.topiam.employee.console.pojo.result.app.AppAccessPolicyResult;
import cn.topiam.employee.console.pojo.save.app.AppAccessPolicyCreateParam;
import cn.topiam.employee.console.pojo.save.app.AppAccountCreateParam;
import cn.topiam.employee.console.service.app.AppAccessPolicyService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -28,8 +28,8 @@ import cn.topiam.employee.common.entity.app.query.AppAccountQuery;
import cn.topiam.employee.console.pojo.result.app.AppAccountListResult;
import cn.topiam.employee.console.pojo.save.app.AppAccountCreateParam;
import cn.topiam.employee.console.service.app.AppAccountService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -32,8 +32,8 @@ import cn.topiam.employee.console.pojo.save.app.AppCreateParam;
import cn.topiam.employee.console.pojo.update.app.AppSaveConfigParam;
import cn.topiam.employee.console.pojo.update.app.AppUpdateParam;
import cn.topiam.employee.console.service.app.AppService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -35,8 +35,8 @@ import cn.topiam.employee.console.pojo.result.app.AppListResult;
import cn.topiam.employee.console.pojo.save.app.AppGroupCreateParam;
import cn.topiam.employee.console.pojo.update.app.AppGroupUpdateParam;
import cn.topiam.employee.console.service.app.AppGroupService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -32,8 +32,8 @@ import cn.topiam.employee.console.pojo.result.authn.IdentityProviderResult;
import cn.topiam.employee.console.pojo.save.authn.IdentityProviderCreateParam;
import cn.topiam.employee.console.pojo.update.authn.IdpUpdateParam;
import cn.topiam.employee.console.service.authn.IdentityProviderService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -37,8 +37,8 @@ import cn.topiam.employee.console.pojo.save.identitysource.IdentitySourceCreateR
import cn.topiam.employee.console.pojo.update.identity.IdentitySourceUpdateParam;
import cn.topiam.employee.console.service.identitysource.IdentitySourceService;
import cn.topiam.employee.identitysource.core.event.IdentitySourceEventUtils;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -29,8 +29,8 @@ import cn.topiam.employee.console.pojo.query.identity.IdentitySourceSyncRecordLi
import cn.topiam.employee.console.pojo.result.identitysource.IdentitySourceSyncHistoryListResult;
import cn.topiam.employee.console.pojo.result.identitysource.IdentitySourceSyncRecordListResult;
import cn.topiam.employee.console.service.identitysource.IdentitySourceSyncService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -46,9 +46,9 @@ import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.core.security.session.ClusterSessionRegistryImpl;
import cn.topiam.employee.core.security.session.Session;
import cn.topiam.employee.support.context.ApplicationContextService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.geo.GeoLocation;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.web.useragent.UserAgent;

View File

@ -32,8 +32,8 @@ import cn.topiam.employee.console.pojo.result.setting.AdministratorResult;
import cn.topiam.employee.console.pojo.save.setting.AdministratorCreateParam;
import cn.topiam.employee.console.pojo.update.setting.AdministratorUpdateParam;
import cn.topiam.employee.console.service.setting.AdministratorService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.result.ApiRestResult;

View File

@ -28,9 +28,9 @@ import cn.topiam.employee.console.pojo.result.setting.GeoIpProviderResult;
import cn.topiam.employee.console.pojo.save.setting.GeoIpProviderSaveParam;
import cn.topiam.employee.console.service.setting.GeoLocationSettingService;
import cn.topiam.employee.support.context.ApplicationContextService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.geo.GeoLocation;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -33,8 +33,8 @@ import cn.topiam.employee.console.service.setting.MessageSettingService;
import cn.topiam.employee.core.context.ContextService;
import cn.topiam.employee.core.message.MsgVariable;
import cn.topiam.employee.core.message.mail.MailMsgEventPublish;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -32,8 +32,8 @@ import cn.topiam.employee.console.pojo.result.setting.EmailTemplateListResult;
import cn.topiam.employee.console.pojo.result.setting.EmailTemplateResult;
import cn.topiam.employee.console.pojo.save.setting.EmailCustomTemplateSaveParam;
import cn.topiam.employee.console.service.setting.MailTemplateService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -27,8 +27,8 @@ import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.console.pojo.result.setting.SecurityBasicConfigResult;
import cn.topiam.employee.console.pojo.save.setting.SecurityBasicSaveParam;
import cn.topiam.employee.console.service.setting.SecuritySettingService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -27,8 +27,8 @@ import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.console.pojo.result.setting.SecurityDefensePolicyConfigResult;
import cn.topiam.employee.console.pojo.save.setting.SecurityDefensePolicyParam;
import cn.topiam.employee.console.service.setting.SecurityDefensePolicyService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -30,8 +30,8 @@ import cn.topiam.employee.console.pojo.result.setting.PasswordPolicyConfigResult
import cn.topiam.employee.console.pojo.result.setting.WeakPasswordLibListResult;
import cn.topiam.employee.console.pojo.save.setting.PasswordPolicySaveParam;
import cn.topiam.employee.console.service.setting.PasswordPolicyService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.RequiredArgsConstructor;

View File

@ -33,8 +33,8 @@ import cn.topiam.employee.console.pojo.save.setting.SmsProviderSaveParam;
import cn.topiam.employee.console.service.setting.MessageSettingService;
import cn.topiam.employee.core.message.MsgVariable;
import cn.topiam.employee.core.message.sms.SmsMsgEventPublish;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.security.password.PasswordGenerator;

View File

@ -27,8 +27,8 @@ import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.console.pojo.result.setting.StorageProviderConfigResult;
import cn.topiam.employee.console.pojo.save.setting.StorageConfigSaveParam;
import cn.topiam.employee.console.service.setting.StorageSettingService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -56,9 +56,9 @@ import static cn.topiam.employee.audit.enums.TargetType.PORTAL;
import static cn.topiam.employee.audit.event.type.EventType.APP_SSO;
import static cn.topiam.employee.audit.event.type.EventType.LOGIN_PORTAL;
import static cn.topiam.employee.audit.service.converter.AuditDataConverter.SORT_EVENT_TIME;
import static cn.topiam.employee.support.util.ImageAvatarUtils.*;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.AvatarUtils.*;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneNumber;
/**
*

View File

@ -35,15 +35,15 @@ import cn.topiam.employee.console.pojo.save.setting.AdministratorCreateParam;
import cn.topiam.employee.console.pojo.update.setting.AdministratorUpdateParam;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.util.BeanUtils;
import cn.topiam.employee.support.util.ImageAvatarUtils;
import jakarta.persistence.criteria.Predicate;
import static cn.topiam.employee.common.entity.setting.AdministratorEntity.*;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_BY;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_TIME;
import static cn.topiam.employee.support.util.ImageAvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.AvatarUtils.bufferedImageToBase64;
import static cn.topiam.employee.support.util.AvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneNumber;
/**
*
@ -69,8 +69,7 @@ public interface AdministratorConverter {
user);
//头像
if (StringUtils.isEmpty(user.getAvatar())) {
convert.setAvatar(ImageAvatarUtils
.bufferedImageToBase64(generateAvatarImg(user.getUsername())));
convert.setAvatar(bufferedImageToBase64(generateAvatarImg(user.getUsername())));
} else {
convert.setAvatar(user.getAvatar());
}

View File

@ -44,8 +44,8 @@ import cn.topiam.employee.support.exception.TopIamException;
import cn.topiam.employee.support.validation.ValidationUtils;
import jakarta.validation.ValidationException;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationServiceImpl.MAXMIND;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationServiceImpl.SHA256_URL;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationParserImpl.MAXMIND;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationParserImpl.SHA256_URL;
import static cn.topiam.employee.core.setting.GeoIpProviderConstants.IPADDRESS_SETTING_NAME;
/**

View File

@ -70,8 +70,7 @@ import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.security.password.PasswordPolicyManager;
import cn.topiam.employee.support.util.BeanUtils;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.validation.annotation.ValidationPhone;
import cn.topiam.employee.support.util.PhoneUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -80,7 +79,8 @@ import static cn.topiam.employee.audit.enums.TargetType.USER_DETAIL;
import static cn.topiam.employee.core.message.sms.SmsMsgEventPublish.USERNAME;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_BY;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_TIME;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.PhoneUtils.PHONE_REGEXP;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneNumber;
/**
* <p>
@ -216,7 +216,7 @@ public class UserServiceImpl implements UserService {
}
//手机号
if (StringUtils.isNotEmpty(param.getPhone())) {
if (!getPhoneNumber(param.getPhone()).matches(ValidationPhone.PHONE_REGEXP)) {
if (!getPhoneNumber(param.getPhone()).matches(PHONE_REGEXP)) {
throw new InfoValidityFailException("手机号格式错误");
}
Boolean validityPhone = userParamCheck(CheckValidityType.PHONE, param.getPhone(), null);
@ -306,8 +306,8 @@ public class UserServiceImpl implements UserService {
detail.orElse(null));
if (Objects.nonNull(userEntity) && StringUtils.isNotEmpty(userEntity.getPhone())) {
StringBuilder phoneAreaCode = new StringBuilder(
userEntity.getPhoneAreaCode().replace(PhoneNumberUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneNumberUtils.PLUS_SIGN);
userEntity.getPhoneAreaCode().replace(PhoneUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneUtils.PLUS_SIGN);
userResult.setPhone(phoneAreaCode + userEntity.getPhone());
}
return userResult;
@ -324,7 +324,7 @@ public class UserServiceImpl implements UserService {
public boolean updateUser(UserUpdateParam param) {
if (StringUtils.isNotBlank(param.getPhone())) {
String phoneNumber = getPhoneNumber(param.getPhone());
if (!phoneNumber.matches(ValidationPhone.PHONE_REGEXP)) {
if (!phoneNumber.matches(PHONE_REGEXP)) {
throw new InfoValidityFailException("手机号格式错误");
}
Boolean validityPhone = userParamCheck(CheckValidityType.PHONE, param.getPhone(),
@ -440,7 +440,7 @@ public class UserServiceImpl implements UserService {
if (CheckValidityType.PHONE.equals(type)) {
try {
//手机号未修改
if (StringUtils.equals(value.replace(PhoneNumberUtils.PLUS_SIGN, ""),
if (StringUtils.equals(value.replace(PhoneUtils.PLUS_SIGN, ""),
entity.getPhoneAreaCode() + entity.getPhone())) {
return true;
}
@ -514,70 +514,70 @@ public class UserServiceImpl implements UserService {
/**
*
*/
private final UserConverter userConverter;
private final UserConverter userConverter;
/**
* UserRepository
*/
private final UserRepository userRepository;
private final UserRepository userRepository;
/**
* UserIdpRepository
*/
private final UserIdpRepository userIdpRepository;
private final UserIdpRepository userIdpRepository;
/**
* AppAccessPolicyRepository
*/
private final AppAccessPolicyRepository appAccessPolicyRepository;
private final AppAccessPolicyRepository appAccessPolicyRepository;
/**
* password encoder
*/
private final PasswordEncoder passwordEncoder;
private final PasswordEncoder passwordEncoder;
/**
*
*/
private final OrganizationRepository organizationRepository;
private final OrganizationRepository organizationRepository;
/**
*
*/
private final OrganizationMemberRepository organizationMemberRepository;
private final OrganizationMemberRepository organizationMemberRepository;
/**
*
*/
private final UserGroupMemberRepository userGroupMemberRepository;
private final UserGroupMemberRepository userGroupMemberRepository;
/**
* Repository
*/
private final UserDetailRepository userDetailsRepository;
private final UserDetailRepository userDetailsRepository;
/**
* Repository
*/
private final UserHistoryPasswordRepository userHistoryPasswordRepository;
private final UserHistoryPasswordRepository userHistoryPasswordRepository;
/**
*
*/
private final MailMsgEventPublish mailMsgEventPublish;
private final MailMsgEventPublish mailMsgEventPublish;
/**
*
*/
private final SmsMsgEventPublish smsMsgEventPublish;
private final SmsMsgEventPublish smsMsgEventPublish;
/**
* PasswordPolicyManager
*/
private final PasswordPolicyManager<UserEntity> passwordPolicyManager;
private final PasswordPolicyManager passwordPolicyManager;
/**
* AuditRepository
*/
private final AuditRepository auditRepository;
private final AuditRepository auditRepository;
}

View File

@ -17,6 +17,7 @@
*/
package cn.topiam.employee.console.service.account.userdetail;
import java.time.LocalDateTime;
import java.util.Optional;
import org.slf4j.Logger;
@ -25,8 +26,13 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import cn.topiam.employee.audit.context.AuditContext;
import cn.topiam.employee.audit.entity.Target;
import cn.topiam.employee.audit.enums.TargetType;
import cn.topiam.employee.common.entity.setting.AdministratorEntity;
import cn.topiam.employee.common.repository.setting.AdministratorRepository;
import cn.topiam.employee.console.service.setting.AdministratorService;
import cn.topiam.employee.support.exception.TopIamException;
import cn.topiam.employee.support.security.password.exception.PasswordValidatedFailException;
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.security.userdetails.UserDetailsService;
@ -75,36 +81,103 @@ public class UserDetailsServiceImpl implements UserDetailsService {
return administratorService.getUserDetails(administrator);
}
@Override
public UserDetails loadUserByPhone(String phone) throws UsernameNotFoundException {
Optional<AdministratorEntity> optional = administratorRepository.findByPhone(phone);
//不存在该用户
if (optional.isEmpty()) {
logger.info("根据手机号未查询该管理员【{}】", phone);
throw new UsernameNotFoundException("用户名或密码错误");
}
return getUserDetails(optional.get());
}
@Override
public UserDetails loadUserByEmail(String email) throws UsernameNotFoundException {
Optional<AdministratorEntity> optional = administratorRepository.findByEmail(email);
//不存在该用户
if (optional.isEmpty()) {
logger.info("根据邮箱未查询该管理员【{}】", email);
throw new UsernameNotFoundException("用户名或密码错误");
}
return getUserDetails(optional.get());
}
@Override
public void changePassword(String username, String newPassword) {
administratorService.forceResetAdministratorPassword(username, newPassword);
AdministratorEntity administrator = findByUsername(username);
forceResetUserPassword(administrator, newPassword);
}
@Override
public void changePassword(String username, String oldPassword, String newPassword) {
AdministratorEntity admin = administratorService.getAdministratorByUsername(username);
boolean matches = passwordEncoder.matches(oldPassword, admin.getPassword());
AdministratorEntity administrator = findByUsername(username);
boolean matches = passwordEncoder.matches(oldPassword, administrator.getPassword());
if (!matches) {
logger.error("用户ID: [{}] 用户名: [{}] 旧密码匹配失败", admin.getId(), admin.getUsername());
logger.error("用户ID: [{}] 用户名: [{}] 旧密码匹配失败", administrator.getId(),
administrator.getUsername());
throw new PasswordValidatedFailException();
}
// 重置密码
administratorService.forceResetAdministratorPassword(admin, newPassword);
forceResetUserPassword(administrator, newPassword);
}
private UserDetails getUserDetails(AdministratorEntity administrator) {
//锁定
if (administrator.isLocked()) {
logger.info("用户【{}】被锁定", administrator.getUsername());
}
//禁用
if (administrator.isDisabled()) {
logger.info("用户【{}】被禁用", administrator.getUsername());
}
return administratorService.getUserDetails(administrator);
}
public void forceResetUserPassword(AdministratorEntity administrator, String password) {
boolean matches = passwordEncoder.matches(password, administrator.getPassword());
if (matches) {
logger.error("用户ID: [{}] 用户名: [{}] 新密码与旧密码相同", administrator.getId(),
administrator.getUsername());
throw new PasswordValidatedFailException("新密码不允许与旧密码相同");
}
password = passwordEncoder.encode(password);
administrator.setPassword(password);
administrator.setLastUpdatePasswordTime(LocalDateTime.now());
administrator.setNeedChangePassword(false);
// 更新密码
administratorRepository.save(administrator);
AuditContext.setTarget(Target.builder().id(administrator.getId())
.name(administrator.getUsername()).type(TargetType.USER).build());
}
public AdministratorEntity findByUsername(String username) {
return administratorRepository.findByUsername(username).orElseThrow(() -> {
AuditContext.setContent("重置密码失败,用户不存在");
logger.warn(AuditContext.getContent());
return new TopIamException("操作失败");
});
}
/**
* AdministratorService
* AdministratorRepository
*/
private final AdministratorService administratorService;
private final AdministratorRepository administratorRepository;
/**
* PasswordEncoder
*/
private final PasswordEncoder passwordEncoder;
private final PasswordEncoder passwordEncoder;
public UserDetailsServiceImpl(AdministratorService administratorService,
PasswordEncoder passwordEncoder) {
this.administratorService = administratorService;
/**
* UserService
*/
private final AdministratorService administratorService;
public UserDetailsServiceImpl(AdministratorRepository administratorRepository,
PasswordEncoder passwordEncoder,
AdministratorService administratorService) {
this.administratorRepository = administratorRepository;
this.passwordEncoder = passwordEncoder;
this.administratorService = administratorService;
}
}

View File

@ -69,10 +69,9 @@ import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.security.password.exception.PasswordValidatedFailException;
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.security.userdetails.UserType;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.validation.annotation.ValidationPhone;
import cn.topiam.employee.support.util.PhoneUtils;
import static cn.topiam.employee.support.constant.EiamConstants.DEFAULT_ADMIN_USERNAME;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.PhoneUtils.*;
/**
* @author TopIAM
@ -115,7 +114,7 @@ public class AdministratorServiceImpl implements AdministratorService {
}
//手机号
if (StringUtils.isNotEmpty(param.getPhone())) {
if (!getPhoneNumber(param.getPhone()).matches(ValidationPhone.PHONE_REGEXP)) {
if (!getPhoneNumber(param.getPhone()).matches(PHONE_REGEXP)) {
throw new InfoValidityFailException("手机号格式错误");
}
Boolean validityPhone = administratorParamCheck(CheckValidityType.PHONE, param.getPhone(), null);
@ -331,7 +330,7 @@ public class AdministratorServiceImpl implements AdministratorService {
if (CheckValidityType.PHONE.equals(type)) {
try {
//手机号未修改
if (StringUtils.equals(value.replace(PhoneNumberUtils.PLUS_SIGN, ""),
if (StringUtils.equals(value.replace(PLUS_SIGN, ""),
entity.getPhoneAreaCode() + entity.getPhone())) {
return true;
}
@ -443,8 +442,8 @@ public class AdministratorServiceImpl implements AdministratorService {
.entityConvertToAdministratorDetailsResult(administrator);
if (Objects.nonNull(administrator) && StringUtils.isNotEmpty(administrator.getPhone())) {
StringBuilder phoneAreaCode = new StringBuilder(
administrator.getPhoneAreaCode().replace(PhoneNumberUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneNumberUtils.PLUS_SIGN);
administrator.getPhoneAreaCode().replace(PhoneUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneUtils.PLUS_SIGN);
result.setPhone(phoneAreaCode + administrator.getPhone());
}
return result;

View File

@ -28,7 +28,7 @@ import cn.topiam.employee.console.pojo.save.setting.GeoIpProviderSaveParam;
import cn.topiam.employee.console.service.setting.GeoLocationSettingService;
import cn.topiam.employee.support.context.ApplicationContextService;
import cn.topiam.employee.support.geo.GeoLocation;
import cn.topiam.employee.support.geo.GeoLocationService;
import cn.topiam.employee.support.geo.GeoLocationParser;
import lombok.extern.slf4j.Slf4j;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.GEO_LOCATION;
@ -80,17 +80,17 @@ public class GeoLocationSettingServiceImpl extends SettingServiceImpl
*/
@Override
public GeoLocation getGeoLocation(String ip) {
return geoLocationService.getGeoLocation(ip);
return geoLocationParser.getGeoLocation(ip);
}
private final GeoLocationService geoLocationService;
private final GeoLocationParser geoLocationParser;
private final GeoLocationSettingConverter geoLocationSettingsConverter;
public GeoLocationSettingServiceImpl(SettingRepository settingsRepository,
GeoLocationService geoLocationService,
GeoLocationParser geoLocationParser,
GeoLocationSettingConverter geoLocationSettingsConverter) {
super(settingsRepository);
this.geoLocationService = geoLocationService;
this.geoLocationParser = geoLocationParser;
this.geoLocationSettingsConverter = geoLocationSettingsConverter;
}
}

View File

@ -55,7 +55,7 @@ import cn.topiam.employee.support.exception.TopIamException;
import cn.topiam.employee.support.security.password.exception.PasswordValidatedFailException;
import cn.topiam.employee.support.security.util.SecurityUtils;
import cn.topiam.employee.support.util.BeanUtils;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.util.PhoneUtils;
import jakarta.servlet.http.HttpSession;
import static cn.topiam.employee.core.message.sms.SmsMsgEventPublish.USERNAME;
@ -64,7 +64,7 @@ import static cn.topiam.employee.support.exception.enums.ExceptionStatus.EX00010
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_BY;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_TIME;
import static cn.topiam.employee.support.util.EmailUtils.isEmailValidate;
import static cn.topiam.employee.support.util.PhoneNumberUtils.isPhoneValidate;
import static cn.topiam.employee.support.util.PhoneUtils.isPhoneValidate;
/**
*
@ -229,7 +229,7 @@ public class UserProfileServiceImpl implements UserProfileService {
} else if (isPhoneValidate(recipient)) {
// 验证在库中是否有手机号
Optional<AdministratorEntity> byPhone = administratorRepository
.findByPhone(PhoneNumberUtils.getPhoneNumber(recipient));
.findByPhone(PhoneUtils.getPhoneNumber(recipient));
if (byPhone.isPresent()) {
otpContextHelp.sendOtp(recipient, SmsType.FORGET_PASSWORD.getCode(),
MessageNoticeChannel.SMS);
@ -253,7 +253,7 @@ public class UserProfileServiceImpl implements UserProfileService {
MessageNoticeChannel.MAIL, recipient, code);
}
} else if (isPhoneValidate(recipient)) {
user = administratorRepository.findByPhone(PhoneNumberUtils.getPhoneNumber(recipient));
user = administratorRepository.findByPhone(PhoneUtils.getPhoneNumber(recipient));
if (user.isPresent()) {
checkOtp = otpContextHelp.checkOtp(SmsType.FORGET_PASSWORD.getCode(),
MessageNoticeChannel.SMS, recipient, code);

View File

@ -33,17 +33,17 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import cn.topiam.employee.common.entity.setting.SettingEntity;
import cn.topiam.employee.common.geo.GeoLocationProviderConfig;
import cn.topiam.employee.common.geo.NoneGeoLocationServiceImpl;
import cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationServiceImpl;
import cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationServiceImpl;
import cn.topiam.employee.common.geo.NoneGeoLocationParserImpl;
import cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationParserImpl;
import cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationParserImpl;
import cn.topiam.employee.common.geo.maxmind.MaxmindProviderConfig;
import cn.topiam.employee.common.jackjson.encrypt.EncryptionModule;
import cn.topiam.employee.common.repository.setting.SettingRepository;
import cn.topiam.employee.core.setting.GeoIpProviderConstants;
import cn.topiam.employee.support.geo.GeoLocationService;
import cn.topiam.employee.support.geo.GeoLocationParser;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.GEO_LOCATION;
import static cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationServiceImpl.IP2REGION;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationServiceImpl.MAXMIND;
import static cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationParserImpl.IP2REGION;
import static cn.topiam.employee.common.geo.maxmind.MaxmindGeoLocationParserImpl.MAXMIND;
/**
*
@ -57,8 +57,8 @@ public class EiamGeoLocationConfiguration {
@RefreshScope
@Bean(value = GEO_LOCATION)
public GeoLocationService geoLocation(SettingRepository settingRepository,
RestTemplate restTemplate) {
public GeoLocationParser geoLocation(SettingRepository settingRepository,
RestTemplate restTemplate) {
try {
ObjectMapper objectMapper = EncryptionModule.deserializerDecrypt();
// 指定序列化输入的类型
@ -72,19 +72,19 @@ public class EiamGeoLocationConfiguration {
GeoLocationProviderConfig.class);
// maxmind
if (MAXMIND.equals(provider.getProvider())) {
return new MaxmindGeoLocationServiceImpl(
return new MaxmindGeoLocationParserImpl(
(MaxmindProviderConfig) provider.getConfig(), restTemplate);
}
// ip2region
if (IP2REGION.equals(provider.getProvider())) {
return new Ip2regionGeoLocationServiceImpl();
return new Ip2regionGeoLocationParserImpl();
}
}
//没有数据默认使用 ip2region
return new Ip2regionGeoLocationServiceImpl();
return new Ip2regionGeoLocationParserImpl();
} catch (IOException e) {
logger.error("Create geo location Exception: {}", e.getMessage(), e);
}
return new NoneGeoLocationServiceImpl();
return new NoneGeoLocationParserImpl();
}
}

View File

@ -23,7 +23,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import cn.topiam.employee.common.constant.ConfigBeanNameConstants;
import cn.topiam.employee.common.entity.account.UserEntity;
import cn.topiam.employee.common.repository.account.UserHistoryPasswordRepository;
import cn.topiam.employee.common.repository.account.UserRepository;
import cn.topiam.employee.common.repository.setting.SettingRepository;
@ -54,11 +53,11 @@ public class EiamPasswordConfiguration {
*/
@Bean(ConfigBeanNameConstants.DEFAULT_PASSWORD_POLICY_MANAGER)
@RefreshScope
public PasswordPolicyManager<UserEntity> passwordPolicyManager(UserRepository userRepository,
UserHistoryPasswordRepository userHistoryPasswordRepository,
SettingRepository settingRepository,
PasswordWeakLib passwordWeakLib,
PasswordEncoder passwordEncoder) {
public PasswordPolicyManager passwordPolicyManager(UserRepository userRepository,
UserHistoryPasswordRepository userHistoryPasswordRepository,
SettingRepository settingRepository,
PasswordWeakLib passwordWeakLib,
PasswordEncoder passwordEncoder) {
return new DefaultPasswordPolicyManager(userRepository, userHistoryPasswordRepository,
settingRepository, passwordWeakLib, passwordEncoder);
}

View File

@ -23,6 +23,7 @@ import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.security.crypto.password.PasswordEncoder;
import cn.topiam.employee.common.entity.account.UserEntity;
@ -46,7 +47,7 @@ import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIE
* @author TopIAM
* Created by support@topiam.cn on 2022/4/17 22:21
*/
public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserEntity> {
public class DefaultPasswordPolicyManager implements PasswordPolicyManager {
public DefaultPasswordPolicyManager(UserRepository userRepository,
UserHistoryPasswordRepository userHistoryPasswordRepository,
@ -71,19 +72,20 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
/**
*
*
* @param userId {@link Long} ID
* @param principal {@link Long}
* @param password {@link String}
*/
@Override
public void validate(UserEntity userId, String password) {
List<PasswordValidator> validators = new ArrayList<>(providers);
if (userId.getId() != null) {
public void validate(@NonNull Object principal, String password) {
if (principal instanceof UserEntity) {
String userId = ((UserEntity) principal).getId();
List<PasswordValidator> validators = new ArrayList<>(providers);
//@formatter:off
validators.add(getPasswordIncludeUserInfoValidator(userId.getId()));
validators.add(getHistoryPasswordValidator(String.valueOf(userId.getId())));
validators.add(getPasswordIncludeUserInfoValidator(userId));
validators.add(getHistoryPasswordValidator(userId));
//@formatter:on
validators.forEach(passwordValidator -> passwordValidator.validate(password));
}
validators.forEach(passwordValidator -> passwordValidator.validate(password));
}
/**
@ -104,6 +106,7 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
//@formatter:off
UserEntity user = optionalUser.get();
return new PasswordIncludeUserInfoValidator(user.getFullName(), user.getNickName(), user.getUsername(), user.getPhone(), user.getEmail());
//@formatter:on
}
}
return new PasswordIncludeUserInfoValidator(false);
@ -115,25 +118,30 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
* @return {@link HistoryPasswordValidator}
*/
private HistoryPasswordValidator getHistoryPasswordValidator(String userId) {
SettingEntity historyCipherCheck = settingRepository.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_HISTORY_PASSWORD_CHECK);
SettingEntity historyCipherCheck = settingRepository
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_HISTORY_PASSWORD_CHECK);
boolean enabled = Objects.isNull(historyCipherCheck)
? Boolean.parseBoolean(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_HISTORY_PASSWORD_CHECK))
: Boolean.parseBoolean(historyCipherCheck.getValue());
? Boolean.parseBoolean(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_HISTORY_PASSWORD_CHECK))
: Boolean.parseBoolean(historyCipherCheck.getValue());
if (enabled) {
SettingEntity historyCipherCheckCount = settingRepository.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_HISTORY_PASSWORD_CHECK_COUNT);
SettingEntity historyCipherCheckCount = settingRepository.findByName(
PasswordPolicySettingConstants.PASSWORD_POLICY_HISTORY_PASSWORD_CHECK_COUNT);
Integer count = Objects.isNull(historyCipherCheckCount)
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_HISTORY_PASSWORD_CHECK_COUNT))
: Integer.valueOf(historyCipherCheckCount.getValue());
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_HISTORY_PASSWORD_CHECK_COUNT))
: Integer.valueOf(historyCipherCheckCount.getValue());
Page<UserHistoryPasswordEntity> entities = userHistoryPasswordRepository.findAll(
Example.of(new UserHistoryPasswordEntity().setUserId(userId)),
PageRequest.of(0, count, Sort.by(Sort.Direction.DESC, LAST_MODIFIED_TIME)));
Example.of(new UserHistoryPasswordEntity().setUserId(userId)),
PageRequest.of(0, count, Sort.by(Sort.Direction.DESC, LAST_MODIFIED_TIME)));
//构建历史密码验证器
new HistoryPasswordValidator(entities.getContent().stream().map(UserHistoryPasswordEntity::getPassword).toList(), passwordEncoder);
return new HistoryPasswordValidator(
entities.getContent().stream().map(UserHistoryPasswordEntity::getPassword).toList(),
passwordEncoder);
}
return new HistoryPasswordValidator(false);
}
/**
*
*
@ -142,16 +150,18 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
private PasswordLengthValidator getPasswordLengthValidator() {
//最小长度
SettingEntity leastLengthEntity = settingRepository
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_LEAST_LENGTH);
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_LEAST_LENGTH);
Integer leastLength = Objects.isNull(leastLengthEntity)
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_LEAST_LENGTH))
: Integer.valueOf(leastLengthEntity.getValue());
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_LEAST_LENGTH))
: Integer.valueOf(leastLengthEntity.getValue());
//最大长度
SettingEntity biggestLengthEntity = settingRepository
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_BIGGEST_LENGTH);
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_BIGGEST_LENGTH);
Integer biggestLength = Objects.isNull(biggestLengthEntity)
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_BIGGEST_LENGTH))
: Integer.valueOf(biggestLengthEntity.getValue());
? Integer.valueOf(PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_BIGGEST_LENGTH))
: Integer.valueOf(biggestLengthEntity.getValue());
return new PasswordLengthValidator(leastLength, biggestLength);
}
@ -163,8 +173,8 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
private PasswordComplexityRuleValidator getPasswordComplexityRuleValidator() {
SettingEntity setting = settingRepository.findByName(PASSWORD_POLICY_COMPLEXITY);
String complexityRule = Objects.isNull(setting)
? PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_COMPLEXITY)
: setting.getValue();
? PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_COMPLEXITY)
: setting.getValue();
PasswordComplexityRule rule = PasswordComplexityRule.getType(complexityRule);
return new PasswordComplexityRuleValidator(rule);
}
@ -175,14 +185,17 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
* @return {@link WeakPasswordValidator}
*/
private WeakPasswordValidator getWeakPasswordValidator() {
SettingEntity setting = settingRepository.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_WEAK_PASSWORD_CHECK);
SettingEntity setting = settingRepository
.findByName(PasswordPolicySettingConstants.PASSWORD_POLICY_WEAK_PASSWORD_CHECK);
String enable = Objects.isNull(setting)
? PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_WEAK_PASSWORD_CHECK)
: setting.getValue();
? PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_WEAK_PASSWORD_CHECK)
: setting.getValue();
if (Boolean.parseBoolean(enable)) {
ArrayList<String> list = new ArrayList<>();
//自定义弱密码
SettingEntity customWeakCipher = settingRepository.findByName(PASSWORD_POLICY_CUSTOM_WEAK_PASSWORD);
SettingEntity customWeakCipher = settingRepository
.findByName(PASSWORD_POLICY_CUSTOM_WEAK_PASSWORD);
if (!Objects.isNull(customWeakCipher)) {
list.addAll(Arrays.asList(customWeakCipher.getValue().split("\n")));
}
@ -194,6 +207,22 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
return new WeakPasswordValidator(false);
}
/**
*
*
* @param userId {@link Long} ID
* @param password {@link String}
*/
@Override
public void validate(@NonNull String userId, String password) {
List<PasswordValidator> validators = new ArrayList<>(providers);
//@formatter:off
validators.add(getPasswordIncludeUserInfoValidator(userId));
validators.add(getHistoryPasswordValidator(userId));
//@formatter:on
validators.forEach(passwordValidator -> passwordValidator.validate(password));
}
/**
*
*
@ -202,8 +231,9 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
private PasswordContinuousSameCharValidator getPasswordContinuousSameCharValidator() {
SettingEntity setting = settingRepository.findByName(PASSWORD_POLICY_NOT_SAME_CHARS);
String rule = Objects.isNull(setting)
? PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_NOT_SAME_CHARS)
: setting.getValue();
? PasswordPolicySettingConstants.PASSWORD_POLICY_DEFAULT_SETTINGS
.get(PASSWORD_POLICY_NOT_SAME_CHARS)
: setting.getValue();
return new PasswordContinuousSameCharValidator(Integer.valueOf(rule));
}
@ -213,21 +243,22 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
* @return {@link PasswordIllegalSequenceValidator}
*/
private PasswordIllegalSequenceValidator getPasswordIllegalSequenceValidator() {
SettingEntity setting = settingRepository.findByName(PASSWORD_POLICY_ILLEGAL_SEQUENCE_CHECK);
SettingEntity setting = settingRepository
.findByName(PASSWORD_POLICY_ILLEGAL_SEQUENCE_CHECK);
String enable = Objects.isNull(setting)
? PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_ILLEGAL_SEQUENCE_CHECK)
: setting.getValue();
? PASSWORD_POLICY_DEFAULT_SETTINGS.get(PASSWORD_POLICY_ILLEGAL_SEQUENCE_CHECK)
: setting.getValue();
return new PasswordIllegalSequenceValidator(Boolean.parseBoolean(enable));
}
/**
*
*/
private final List<PasswordValidator> providers;
private final List<PasswordValidator> providers;
/**
*
*/
private final UserRepository userRepository;
private final UserRepository userRepository;
/**
*
*/
@ -235,13 +266,13 @@ public class DefaultPasswordPolicyManager implements PasswordPolicyManager<UserE
/**
*
*/
private final SettingRepository settingRepository;
private final SettingRepository settingRepository;
/**
*
*/
private final PasswordWeakLib passwordWeakLib;
private final PasswordWeakLib passwordWeakLib;
/**
* PasswordEncoder
*/
private final PasswordEncoder passwordEncoder;
private final PasswordEncoder passwordEncoder;
}

View File

@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import cn.topiam.employee.openapi.constant.OpenApiStatus;
import cn.topiam.employee.support.security.web.AbstractAuthenticationEntryPoint;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import lombok.Data;
@ -43,6 +44,10 @@ import jakarta.servlet.http.HttpServletResponse;
*/
public final class AccessTokenAuthenticationEntryPoint extends AbstractAuthenticationEntryPoint {
public AccessTokenAuthenticationEntryPoint(UserAgentParser userAgentParser) {
super(userAgentParser);
}
/**
* Collect error details from the provided parameters and format according to RFC
* 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and

View File

@ -23,7 +23,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import cn.topiam.employee.EiamOpenApiApplication;
import cn.topiam.employee.support.util.AppVersionUtils;
import cn.topiam.employee.support.util.VersionUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
@ -71,7 +71,7 @@ public class OpenApiConfiguration {
//内容
.contact(contact)
//版本
.version(AppVersionUtils.getVersion(EiamOpenApiApplication.class));
.version(VersionUtils.getVersion(EiamOpenApiApplication.class));
}
@Bean

View File

@ -34,6 +34,7 @@ import cn.topiam.employee.openapi.authorization.AccessTokenAuthenticationFilter;
import cn.topiam.employee.openapi.authorization.AccessTokenAuthenticationProvider;
import cn.topiam.employee.openapi.authorization.store.AccessTokenStore;
import cn.topiam.employee.openapi.authorization.store.RedisAccessTokenStore;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.DEFAULT_SECURITY_FILTER_CHAIN;
import static cn.topiam.employee.openapi.constant.OpenApiV1Constants.AUTH_PATH;
import static cn.topiam.employee.openapi.constant.OpenApiV1Constants.OPEN_API_V1_PATH;
@ -74,7 +75,7 @@ public class OpenApiSecurityConfiguration {
//关闭 session
http.sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
//异常处理器
http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(new AccessTokenAuthenticationEntryPoint()));
http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(new AccessTokenAuthenticationEntryPoint(userAgentParser)));
http.addFilterBefore(new AccessTokenAuthenticationFilter(providerManager),BasicAuthenticationFilter.class);
return http.build();
//@formatter:on
@ -90,4 +91,11 @@ public class OpenApiSecurityConfiguration {
public AccessTokenStore tokenStore(RedisTemplate<Object, Object> redisTemplate) {
return new RedisAccessTokenStore(redisTemplate);
}
private final UserAgentParser userAgentParser;
public OpenApiSecurityConfiguration(UserAgentParser userAgentParser) {
this.userAgentParser = userAgentParser;
}
}

View File

@ -37,9 +37,9 @@ import cn.topiam.employee.openapi.pojo.update.UserUpdateParam;
import cn.topiam.employee.support.context.ApplicationContextService;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.security.userdetails.DataOrigin;
import static cn.topiam.employee.support.util.ImageAvatarUtils.getRandomAvatar;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.AvatarUtils.getRandomAvatar;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneAreaCode;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneNumber;
/**
*

View File

@ -28,8 +28,8 @@ import cn.topiam.employee.openapi.common.OpenApiResponse;
import cn.topiam.employee.openapi.pojo.result.AppAccountListResult;
import cn.topiam.employee.openapi.pojo.save.AppAccountCreateParam;
import cn.topiam.employee.openapi.service.AppAccountService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;

View File

@ -31,8 +31,8 @@ import cn.topiam.employee.openapi.pojo.result.OrganizationResult;
import cn.topiam.employee.openapi.pojo.save.OrganizationCreateParam;
import cn.topiam.employee.openapi.pojo.update.OrganizationUpdateParam;
import cn.topiam.employee.openapi.service.OrganizationService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import lombok.RequiredArgsConstructor;

View File

@ -31,8 +31,8 @@ import cn.topiam.employee.openapi.pojo.result.UserResult;
import cn.topiam.employee.openapi.pojo.save.UserCreateParam;
import cn.topiam.employee.openapi.pojo.update.UserUpdateParam;
import cn.topiam.employee.openapi.service.UserService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;

View File

@ -59,8 +59,7 @@ import cn.topiam.employee.support.repository.page.domain.Page;
import cn.topiam.employee.support.repository.page.domain.PageModel;
import cn.topiam.employee.support.security.password.PasswordPolicyManager;
import cn.topiam.employee.support.util.BeanUtils;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.validation.annotation.ValidationPhone;
import cn.topiam.employee.support.util.PhoneUtils;
import lombok.extern.slf4j.Slf4j;
import static cn.topiam.employee.audit.enums.TargetType.USER;
@ -68,7 +67,8 @@ import static cn.topiam.employee.audit.enums.TargetType.USER_DETAIL;
import static cn.topiam.employee.core.message.sms.SmsMsgEventPublish.USERNAME;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_BY;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_TIME;
import static cn.topiam.employee.support.util.PhoneNumberUtils.getPhoneNumber;
import static cn.topiam.employee.support.util.PhoneUtils.PHONE_REGEXP;
import static cn.topiam.employee.support.util.PhoneUtils.getPhoneNumber;
/**
* <p>
@ -128,7 +128,7 @@ public class UserServiceImpl implements UserService {
}
//手机号
if (StringUtils.isNotEmpty(param.getPhone())) {
if (!getPhoneNumber(param.getPhone()).matches(ValidationPhone.PHONE_REGEXP)) {
if (!getPhoneNumber(param.getPhone()).matches(PHONE_REGEXP)) {
throw new OpenApiException(OpenApiStatus.MOBILE_NOT_VALID);
}
Boolean validityPhone = userParamCheck(CheckValidityType.PHONE, param.getPhone(), null);
@ -206,8 +206,8 @@ public class UserServiceImpl implements UserService {
detail.orElse(null));
if (Objects.nonNull(userEntity) && StringUtils.isNotEmpty(userEntity.getPhone())) {
StringBuilder phoneAreaCode = new StringBuilder(
userEntity.getPhoneAreaCode().replace(PhoneNumberUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneNumberUtils.PLUS_SIGN);
userEntity.getPhoneAreaCode().replace(PhoneUtils.PLUS_SIGN, ""));
phoneAreaCode.insert(0, PhoneUtils.PLUS_SIGN);
userResult.setPhone(phoneAreaCode + userEntity.getPhone());
}
return userResult;
@ -223,7 +223,7 @@ public class UserServiceImpl implements UserService {
public void updateUser(UserUpdateParam param) {
if (StringUtils.isNotBlank(param.getPhone())) {
String phoneNumber = getPhoneNumber(param.getPhone());
if (!phoneNumber.matches(ValidationPhone.PHONE_REGEXP)) {
if (!phoneNumber.matches(PHONE_REGEXP)) {
throw new OpenApiException(OpenApiStatus.MOBILE_NOT_VALID);
}
Boolean validityPhone = userParamCheck(CheckValidityType.PHONE, param.getPhone(),
@ -342,7 +342,7 @@ public class UserServiceImpl implements UserService {
if (CheckValidityType.PHONE.equals(type)) {
try {
//手机号未修改
if (StringUtils.equals(value.replace(PhoneNumberUtils.PLUS_SIGN, ""),
if (StringUtils.equals(value.replace(PhoneUtils.PLUS_SIGN, ""),
entity.getPhoneAreaCode() + entity.getPhone())) {
return true;
}
@ -377,42 +377,42 @@ public class UserServiceImpl implements UserService {
/**
*
*/
private final UserConverter userConverter;
private final UserConverter userConverter;
/**
* UserRepository
*/
private final UserRepository userRepository;
private final UserRepository userRepository;
/**
*
*/
private final OrganizationMemberRepository organizationMemberRepository;
private final OrganizationMemberRepository organizationMemberRepository;
/**
*
*/
private final UserGroupMemberRepository userGroupMemberRepository;
private final UserGroupMemberRepository userGroupMemberRepository;
/**
* Repository
*/
private final UserDetailRepository userDetailsRepository;
private final UserDetailRepository userDetailsRepository;
/**
*
*/
private final MailMsgEventPublish mailMsgEventPublish;
private final MailMsgEventPublish mailMsgEventPublish;
/**
*
*/
private final SmsMsgEventPublish smsMsgEventPublish;
private final SmsMsgEventPublish smsMsgEventPublish;
/**
* PasswordPolicyManager
*/
private final PasswordPolicyManager<UserEntity> passwordPolicyManager;
private final PasswordPolicyManager passwordPolicyManager;
public UserServiceImpl(UserConverter userConverter, UserRepository userRepository,
OrganizationMemberRepository organizationMemberRepository,
@ -420,7 +420,7 @@ public class UserServiceImpl implements UserService {
UserDetailRepository userDetailsRepository,
MailMsgEventPublish mailMsgEventPublish,
SmsMsgEventPublish smsMsgEventPublish,
PasswordPolicyManager<UserEntity> passwordPolicyManager) {
PasswordPolicyManager passwordPolicyManager) {
this.userConverter = userConverter;
this.userRepository = userRepository;
this.organizationMemberRepository = organizationMemberRepository;

View File

@ -28,6 +28,7 @@ import cn.topiam.employee.core.context.ContextService;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.security.web.AbstractAuthenticationEntryPoint;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@ -86,4 +87,8 @@ public class PortalAuthenticationEntryPoint extends AbstractAuthenticationEntryP
response.sendRedirect(ContextService.getPortalLoginUrl());
}
}
public PortalAuthenticationEntryPoint(UserAgentParser userAgentParser) {
super(userAgentParser);
}
}

View File

@ -61,7 +61,7 @@ import static cn.topiam.employee.core.context.ContextService.getPortalPublicBase
import static cn.topiam.employee.support.constant.EiamConstants.CAPTCHA_CODE_SESSION;
import static cn.topiam.employee.support.context.ServletContextService.isHtmlRequest;
import static cn.topiam.employee.support.security.authentication.AuthenticationProvider.USERNAME_PASSWORD;
import static cn.topiam.employee.support.security.savedredirect.JumpController.JUMP_PATH;
import static cn.topiam.employee.support.security.savedredirect.JumpConstants.JUMP_PATH;
/**
*

View File

@ -22,7 +22,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import cn.topiam.employee.EiamPortalApplication;
import cn.topiam.employee.support.util.AppVersionUtils;
import cn.topiam.employee.support.util.VersionUtils;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
@ -59,7 +59,7 @@ public class PortalApiConfiguration {
//内容
.contact(contact)
//版本
.version(AppVersionUtils.getVersion(EiamPortalApplication.class));
.version(VersionUtils.getVersion(EiamPortalApplication.class));
}
/**

View File

@ -48,6 +48,7 @@ import cn.topiam.employee.core.setting.SecuritySettingConstants;
import cn.topiam.employee.portal.authentication.*;
import cn.topiam.employee.support.redis.KeyStringRedisSerializer;
import cn.topiam.employee.support.security.csrf.SpaCsrfTokenRequestHandler;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK;
import static org.springframework.web.cors.CorsConfiguration.ALL;
@ -150,7 +151,8 @@ public class AbstractSecurityConfiguration {
*/
public Customizer<ExceptionHandlingConfigurer<HttpSecurity>> withExceptionConfigurerDefaults() {
return configurer -> {
configurer.authenticationEntryPoint(new PortalAuthenticationEntryPoint());
configurer
.authenticationEntryPoint(new PortalAuthenticationEntryPoint(userAgentParser));
configurer.accessDeniedHandler(new PortalAccessDeniedHandler());
configurer
.withObjectPostProcessor(new ObjectPostProcessor<ExceptionTranslationFilter>() {
@ -219,11 +221,15 @@ public class AbstractSecurityConfiguration {
};
}
private final UserAgentParser userAgentParser;
private final SettingRepository settingRepository;
public AbstractSecurityConfiguration(SettingRepository settingRepository) {
public AbstractSecurityConfiguration(UserAgentParser userAgentParser,
SettingRepository settingRepository) {
Assert.notNull(settingRepository, "The userAgentParser cannot be null");
Assert.notNull(settingRepository, "The settingRepository cannot be null");
this.settingRepository = settingRepository;
this.userAgentParser = userAgentParser;
}
}

View File

@ -41,6 +41,7 @@ import cn.topiam.employee.protocol.form.RedisFormAuthorizationService;
import cn.topiam.employee.protocol.form.authentication.FormAuthenticationFailureEventListener;
import cn.topiam.employee.protocol.form.authentication.FormAuthenticationSuccessEventListener;
import cn.topiam.employee.protocol.form.configurers.FormAuthorizationServerConfigurer;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static org.springframework.security.config.http.SessionCreationPolicy.NEVER;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.FORM_PROTOCOL_SECURITY_FILTER_CHAIN;
@ -54,10 +55,6 @@ import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.FORM_PR
@Configuration(proxyBeanMethods = false)
public class FormProtocolSecurityConfiguration extends AbstractSecurityConfiguration {
public FormProtocolSecurityConfiguration(SettingRepository settingRepository) {
super(settingRepository);
}
/**
* FormProtocolSecurityFilterChain
*
@ -71,7 +68,7 @@ public class FormProtocolSecurityConfiguration extends AbstractSecurityConfigura
//@formatter:off
httpSecurity.getSharedObject(AuthenticationManagerBuilder.class).parentAuthenticationManager(null);
//Form IDP 配置
FormAuthorizationServerConfigurer serverConfigurer = new FormAuthorizationServerConfigurer();
FormAuthorizationServerConfigurer serverConfigurer = new FormAuthorizationServerConfigurer(userAgentParser);
RequestMatcher endpointsMatcher = serverConfigurer.getEndpointsMatcher();
httpSecurity.securityMatcher(endpointsMatcher)
.authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
@ -123,4 +120,12 @@ public class FormProtocolSecurityConfiguration extends AbstractSecurityConfigura
applicationServiceLoader);
}
public FormProtocolSecurityConfiguration(SettingRepository settingRepository,
UserAgentParser userAgentParser) {
super(userAgentParser, settingRepository);
this.userAgentParser = userAgentParser;
}
private final UserAgentParser userAgentParser;
}

View File

@ -41,6 +41,7 @@ import cn.topiam.employee.protocol.jwt.RedisJwtAuthorizationService;
import cn.topiam.employee.protocol.jwt.authentication.JwtAuthenticationFailureEventListener;
import cn.topiam.employee.protocol.jwt.authentication.JwtAuthenticationSuccessEventListener;
import cn.topiam.employee.protocol.jwt.configurers.JwtAuthorizationServerConfigurer;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static org.springframework.security.config.http.SessionCreationPolicy.NEVER;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.JWT_PROTOCOL_SECURITY_FILTER_CHAIN;
@ -54,10 +55,6 @@ import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.JWT_PRO
@Configuration(proxyBeanMethods = false)
public class JwtProtocolSecurityConfiguration extends AbstractSecurityConfiguration {
public JwtProtocolSecurityConfiguration(SettingRepository settingRepository) {
super(settingRepository);
}
/**
* JwtProtocolSecurityFilterChain
*
@ -71,7 +68,7 @@ public class JwtProtocolSecurityConfiguration extends AbstractSecurityConfigurat
//@formatter:off
httpSecurity.getSharedObject(AuthenticationManagerBuilder.class).parentAuthenticationManager(null);
//Jwt IDP 配置
JwtAuthorizationServerConfigurer serverConfigurer = new JwtAuthorizationServerConfigurer();
JwtAuthorizationServerConfigurer serverConfigurer = new JwtAuthorizationServerConfigurer(userAgentParser);
RequestMatcher endpointsMatcher = serverConfigurer.getEndpointsMatcher();
httpSecurity.securityMatcher(endpointsMatcher)
.authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
@ -123,4 +120,12 @@ public class JwtProtocolSecurityConfiguration extends AbstractSecurityConfigurat
applicationServiceLoader);
}
private final UserAgentParser userAgentParser;
public JwtProtocolSecurityConfiguration(SettingRepository settingRepository,
UserAgentParser userAgentParser) {
super(userAgentParser, settingRepository);
this.userAgentParser = userAgentParser;
}
}

View File

@ -61,6 +61,7 @@ import cn.topiam.employee.common.repository.app.AppOidcConfigRepository;
import cn.topiam.employee.common.repository.setting.SettingRepository;
import cn.topiam.employee.support.jackjson.SupportJackson2Module;
import cn.topiam.employee.support.redis.KeyStringRedisSerializer;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static org.springframework.security.config.http.SessionCreationPolicy.NEVER;
import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.OIDC_PROTOCOL_SECURITY_FILTER_CHAIN;
@ -75,10 +76,6 @@ import static cn.topiam.employee.common.constant.ConfigBeanNameConstants.OIDC_PR
@Configuration(proxyBeanMethods = false)
public class OidcProtocolSecurityConfiguration extends AbstractSecurityConfiguration {
public OidcProtocolSecurityConfiguration(SettingRepository settingRepository) {
super(settingRepository);
}
/**
* OIDC
*
@ -91,7 +88,7 @@ public class OidcProtocolSecurityConfiguration extends AbstractSecurityConfigura
AccessTokenAuthenticationManagerResolver authenticationManagerResolver) throws Exception {
//@formatter:off
httpSecurity.getSharedObject(AuthenticationManagerBuilder.class).parentAuthenticationManager(null);
OAuth2AuthorizationServerConfigurer serverConfigurer = new OAuth2AuthorizationServerConfigurer();
OAuth2AuthorizationServerConfigurer serverConfigurer = new OAuth2AuthorizationServerConfigurer(userAgentParser);
RequestMatcher endpointsMatcher = serverConfigurer.getEndpointsMatcher();
OrRequestMatcher requestMatcher = new OrRequestMatcher(endpointsMatcher);
httpSecurity
@ -245,4 +242,12 @@ public class OidcProtocolSecurityConfiguration extends AbstractSecurityConfigura
public OidcOpenApiCustomizer oidcOpenApiCustomizer() {
return new OidcOpenApiCustomizer();
}
public OidcProtocolSecurityConfiguration(SettingRepository settingRepository,
UserAgentParser userAgentParser) {
super(userAgentParser, settingRepository);
this.userAgentParser = userAgentParser;
}
private final UserAgentParser userAgentParser;
}

View File

@ -73,10 +73,11 @@ import cn.topiam.employee.core.security.password.task.impl.PasswordExpireWarnTas
import cn.topiam.employee.core.security.task.UserExpireLockTask;
import cn.topiam.employee.core.security.task.UserUnlockTask;
import cn.topiam.employee.portal.authentication.*;
import cn.topiam.employee.support.geo.GeoLocationService;
import cn.topiam.employee.support.geo.GeoLocationParser;
import cn.topiam.employee.support.jackjson.SupportJackson2Module;
import cn.topiam.employee.support.security.authentication.WebAuthenticationDetailsSource;
import cn.topiam.employee.support.security.configurer.FormLoginConfigurer;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static org.springframework.http.HttpMethod.*;
import static org.springframework.security.config.Customizer.withDefaults;
@ -435,12 +436,13 @@ public class PortalSecurityConfiguration extends AbstractSecurityConfiguration
/**
* WebAuthenticationDetailsSource
*
* @param geoLocationService {@link GeoLocationService}
* @param geoLocationParser {@link GeoLocationParser}
* @return {@link WebAuthenticationDetailsSource}
*/
@Bean
public WebAuthenticationDetailsSource authenticationDetailsSource(GeoLocationService geoLocationService) {
return new WebAuthenticationDetailsSource(geoLocationService);
public WebAuthenticationDetailsSource authenticationDetailsSource(GeoLocationParser geoLocationParser,
UserAgentParser userAgentParser) {
return new WebAuthenticationDetailsSource(geoLocationParser, userAgentParser);
}
/**
@ -478,7 +480,8 @@ public class PortalSecurityConfiguration extends AbstractSecurityConfiguration
this.loader = classLoader;
}
public PortalSecurityConfiguration(UserRepository userRepository,
public PortalSecurityConfiguration(UserAgentParser userAgentParser,
UserRepository userRepository,
UserDetailsService userDetailsService,
OtpContextHelp otpContextHelp,
PasswordEncoder passwordEncoder,
@ -486,7 +489,7 @@ public class PortalSecurityConfiguration extends AbstractSecurityConfiguration
SettingRepository settingRepository,
RegisteredIdentityProviderClientRepository registeredIdentityProviderClientRepository,
IdentityProviderAuthenticationService identityProviderAuthenticationService) {
super(settingRepository);
super(userAgentParser, settingRepository);
this.userRepository = userRepository;
this.userDetailsService = userDetailsService;
this.otpContextHelp = otpContextHelp;

View File

@ -29,8 +29,8 @@ import cn.topiam.employee.audit.annotation.Audit;
import cn.topiam.employee.audit.event.type.EventType;
import cn.topiam.employee.portal.pojo.request.AppAccountRequest;
import cn.topiam.employee.portal.service.AppAccountService;
import cn.topiam.employee.support.demo.Preview;
import cn.topiam.employee.support.lock.Lock;
import cn.topiam.employee.support.preview.Preview;
import cn.topiam.employee.support.result.ApiRestResult;
import lombok.AllArgsConstructor;

View File

@ -28,15 +28,16 @@ import org.springframework.web.bind.annotation.RestController;
import cn.topiam.employee.common.entity.account.UserEntity;
import cn.topiam.employee.core.security.util.UserUtils;
import cn.topiam.employee.support.result.ApiRestResult;
import cn.topiam.employee.support.util.DesensitizationUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.oas.annotations.media.Schema;
import static cn.topiam.employee.common.constant.SessionConstants.CURRENT_USER;
import static cn.topiam.employee.support.util.ImageAvatarUtils.bufferedImageToBase64;
import static cn.topiam.employee.support.util.ImageAvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.AvatarUtils.bufferedImageToBase64;
import static cn.topiam.employee.support.util.AvatarUtils.generateAvatarImg;
import static cn.topiam.employee.support.util.DesensitizationUtils.emailEncrypt;
import static cn.topiam.employee.support.util.DesensitizationUtils.phoneEncrypt;
/**
*
@ -70,9 +71,9 @@ public class CurrentUserEndpoint {
result.setAvatar(user.getAvatar());
}
//邮箱
result.setEmail(DesensitizationUtil.emailEncrypt(user.getEmail()));
result.setEmail(emailEncrypt(user.getEmail()));
//手机号
result.setPhone(DesensitizationUtil.phoneEncrypt(user.getPhone()));
result.setPhone(phoneEncrypt(user.getPhone()));
return ApiRestResult.ok(result);
}

View File

@ -65,7 +65,7 @@ import cn.topiam.employee.support.security.password.exception.PasswordValidatedF
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.security.util.SecurityUtils;
import cn.topiam.employee.support.util.BeanUtils;
import cn.topiam.employee.support.util.PhoneNumberUtils;
import cn.topiam.employee.support.util.PhoneUtils;
import lombok.extern.slf4j.Slf4j;
@ -77,7 +77,7 @@ import static cn.topiam.employee.support.exception.enums.ExceptionStatus.EX00010
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_BY;
import static cn.topiam.employee.support.repository.base.BaseEntity.LAST_MODIFIED_TIME;
import static cn.topiam.employee.support.util.EmailUtils.isEmailValidate;
import static cn.topiam.employee.support.util.PhoneNumberUtils.isPhoneValidate;
import static cn.topiam.employee.support.util.PhoneUtils.isPhoneValidate;
/**
* @author TopIAM
@ -263,7 +263,7 @@ public class AccountServiceImpl implements AccountService {
} else if (isPhoneValidate(recipient)) {
// 验证在库中是否有手机号
Optional<UserEntity> optional = userRepository
.findByPhone(PhoneNumberUtils.getPhoneNumber(recipient));
.findByPhone(PhoneUtils.getPhoneNumber(recipient));
if (optional.isPresent()) {
otpContextHelp.sendOtp(recipient, SmsType.FORGET_PASSWORD.getCode(),
MessageNoticeChannel.SMS);
@ -287,7 +287,7 @@ public class AccountServiceImpl implements AccountService {
MessageNoticeChannel.MAIL, recipient, code);
}
} else if (isPhoneValidate(recipient)) {
optional = userRepository.findByPhone(PhoneNumberUtils.getPhoneNumber(recipient));
optional = userRepository.findByPhone(PhoneUtils.getPhoneNumber(recipient));
if (optional.isPresent()) {
checkOtp = otpContextHelp.checkOtp(SmsType.FORGET_PASSWORD.getCode(),
MessageNoticeChannel.SMS, recipient, code);
@ -410,62 +410,62 @@ public class AccountServiceImpl implements AccountService {
/**
* Executor
*/
private final Executor executor;
private final Executor executor;
/**
* AccountConverter
*/
private final AccountConverter accountConverter;
private final AccountConverter accountConverter;
/**
* PasswordEncoder
*/
private final PasswordEncoder passwordEncoder;
private final PasswordEncoder passwordEncoder;
/**
* UserRepository
*/
private final UserRepository userRepository;
private final UserRepository userRepository;
/**
* Repository
*/
private final UserDetailRepository userDetailsRepository;
private final UserDetailRepository userDetailsRepository;
/**
* SessionRegistry
*/
private final SessionRegistry sessionRegistry;
private final SessionRegistry sessionRegistry;
/**
* OtpContextHelp
*/
private final OtpContextHelp otpContextHelp;
private final OtpContextHelp otpContextHelp;
/**
* SmsMsgEventPublish
*/
private final SmsMsgEventPublish smsMsgEventPublish;
private final SmsMsgEventPublish smsMsgEventPublish;
/**
* StringRedisTemplate
*/
private final StringRedisTemplate stringRedisTemplate;
private final StringRedisTemplate stringRedisTemplate;
/**
* PasswordPolicyManager
*/
private final PasswordPolicyManager<UserEntity> passwordPolicyManager;
private final PasswordPolicyManager passwordPolicyManager;
/**
* IdentityProviderRepository
*/
private final IdentityProviderRepository identityProviderRepository;
private final IdentityProviderRepository identityProviderRepository;
/**
* UserAuthnBindRepository
*/
private final UserIdpRepository userIdpRepository;
private final UserIdpRepository userIdpRepository;
public AccountServiceImpl(AsyncConfigurer asyncConfigurer, AccountConverter accountConverter,
PasswordEncoder passwordEncoder, UserRepository userRepository,
@ -473,7 +473,7 @@ public class AccountServiceImpl implements AccountService {
SessionRegistry sessionRegistry, OtpContextHelp otpContextHelp,
SmsMsgEventPublish smsMsgEventPublish,
StringRedisTemplate stringRedisTemplate,
PasswordPolicyManager<UserEntity> passwordPolicyManager,
PasswordPolicyManager passwordPolicyManager,
IdentityProviderRepository identityProviderRepository,
UserIdpRepository userIdpRepository) {
this.executor = asyncConfigurer.getAsyncExecutor();

View File

@ -17,13 +17,23 @@
*/
package cn.topiam.employee.portal.service.userdetail;
import java.time.LocalDateTime;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import cn.topiam.employee.audit.context.AuditContext;
import cn.topiam.employee.audit.entity.Target;
import cn.topiam.employee.audit.enums.TargetType;
import cn.topiam.employee.common.entity.account.UserEntity;
import cn.topiam.employee.common.repository.account.UserRepository;
import cn.topiam.employee.portal.service.UserService;
import cn.topiam.employee.support.exception.TopIamException;
import cn.topiam.employee.support.security.password.exception.PasswordValidatedFailException;
import cn.topiam.employee.support.security.userdetails.UserDetails;
import cn.topiam.employee.support.security.userdetails.UserDetailsService;
@ -60,21 +70,99 @@ public class UserDetailsServiceImpl implements UserDetailsService {
}
@Override
public void changePassword(String username, String newPassword) {
public UserDetails loadUserByPhone(String phone) throws UsernameNotFoundException {
Optional<UserEntity> optional = userRepository.findByPhone(phone);
//不存在该用户
if (optional.isEmpty()) {
logger.info("根据手机号未查询该管理员【{}】", phone);
throw new UsernameNotFoundException("用户名或密码错误");
}
return getUserDetails(optional.get());
}
@Override
public UserDetails loadUserByEmail(String email) throws UsernameNotFoundException {
Optional<UserEntity> optional = userRepository.findByEmail(email);
//不存在该用户
if (optional.isEmpty()) {
logger.info("根据邮箱未查询该管理员【{}】", email);
throw new UsernameNotFoundException("用户名或密码错误");
}
return getUserDetails(optional.get());
}
private UserDetails getUserDetails(UserEntity user) {
//锁定
if (user.isLocked()) {
logger.info("用户【{}】被锁定", user.getUsername());
}
//禁用
if (user.isDisabled()) {
logger.info("用户【{}】被禁用", user.getUsername());
}
return userService.getUserDetails(user);
}
public void forceResetUserPassword(UserEntity user, String password) {
boolean matches = passwordEncoder.matches(password, user.getPassword());
if (matches) {
logger.error("用户ID: [{}] 用户名: [{}] 新密码与旧密码相同", user.getId(), user.getUsername());
throw new PasswordValidatedFailException("新密码不允许与旧密码相同");
}
password = passwordEncoder.encode(password);
user.setPassword(password);
user.setLastUpdatePasswordTime(LocalDateTime.now());
user.setNeedChangePassword(false);
// 更新密码
userRepository.save(user);
AuditContext.setTarget(Target.builder().id(user.getId()).name(user.getUsername())
.type(TargetType.USER).build());
}
@Override
public void changePassword(String username, String newPassword) {
UserEntity user = findByUsername(username);
forceResetUserPassword(user, newPassword);
}
@Override
public void changePassword(String username, String oldPassword, String newPassword) {
UserEntity user = findByUsername(username);
boolean matches = passwordEncoder.matches(oldPassword, user.getPassword());
if (!matches) {
logger.error("用户ID: [{}] 用户名: [{}] 旧密码匹配失败", user.getId(), user.getUsername());
throw new PasswordValidatedFailException();
}
forceResetUserPassword(user, newPassword);
}
public UserEntity findByUsername(String username) {
return userRepository.findByUsername(username).orElseThrow(() -> {
AuditContext.setContent("重置密码失败,用户不存在");
logger.warn(AuditContext.getContent());
return new TopIamException("操作失败");
});
}
/**
* UserService
*/
private final UserService userService;
private final UserRepository userRepository;
public UserDetailsServiceImpl(UserService userService) {
/**
* PasswordEncoder
*/
private final PasswordEncoder passwordEncoder;
/**
* UserService
*/
private final UserService userService;
public UserDetailsServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder,
UserService userService) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.userService = userService;
}
}

View File

@ -30,6 +30,7 @@ import cn.topiam.employee.support.security.savedredirect.HttpSessionRedirectCach
import cn.topiam.employee.support.security.savedredirect.RedirectCache;
import cn.topiam.employee.support.security.web.AbstractAuthenticationEntryPoint;
import cn.topiam.employee.support.util.HttpResponseUtils;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@ -46,6 +47,10 @@ public class UnauthorizedAuthenticationEntryPoint extends AbstractAuthentication
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final RedirectCache redirectCache = new HttpSessionRedirectCache();
public UnauthorizedAuthenticationEntryPoint(UserAgentParser userAgentParser) {
super(userAgentParser);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {

View File

@ -33,6 +33,7 @@ import cn.topiam.employee.protocol.code.EndpointMatcher;
import cn.topiam.employee.protocol.code.UnauthorizedAuthenticationEntryPoint;
import cn.topiam.employee.protocol.code.configurer.AbstractConfigurer;
import cn.topiam.employee.protocol.form.context.FormAuthorizationServerContextFilter;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static cn.topiam.employee.protocol.code.configurer.AuthenticationUtils.getApplicationServiceLoader;
/**
@ -67,8 +68,8 @@ public final class FormAuthorizationServerConfigurer extends
httpSecurity.exceptionHandling(exceptionHandling -> {
if (exceptionHandling != null) {
//身份验证入口点
exceptionHandling
.authenticationEntryPoint(new UnauthorizedAuthenticationEntryPoint());
exceptionHandling.authenticationEntryPoint(
new UnauthorizedAuthenticationEntryPoint(userAgentParser));
}
});
}
@ -97,4 +98,9 @@ public final class FormAuthorizationServerConfigurer extends
return configurers;
}
private final UserAgentParser userAgentParser;
public FormAuthorizationServerConfigurer(UserAgentParser userAgentParser) {
this.userAgentParser = userAgentParser;
}
}

View File

@ -33,6 +33,7 @@ import cn.topiam.employee.protocol.code.EndpointMatcher;
import cn.topiam.employee.protocol.code.UnauthorizedAuthenticationEntryPoint;
import cn.topiam.employee.protocol.code.configurer.AbstractConfigurer;
import cn.topiam.employee.protocol.jwt.context.JwtAuthorizationServerContextFilter;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static cn.topiam.employee.protocol.code.configurer.AuthenticationUtils.getApplicationServiceLoader;
/**
@ -67,8 +68,8 @@ public final class JwtAuthorizationServerConfigurer extends
httpSecurity.exceptionHandling(exceptionHandling -> {
if (exceptionHandling != null) {
//身份验证入口点
exceptionHandling
.authenticationEntryPoint(new UnauthorizedAuthenticationEntryPoint());
exceptionHandling.authenticationEntryPoint(
new UnauthorizedAuthenticationEntryPoint(userAgentParser));
}
});
@ -99,4 +100,9 @@ public final class JwtAuthorizationServerConfigurer extends
return configurers;
}
private final UserAgentParser userAgentParser;
public JwtAuthorizationServerConfigurer(UserAgentParser userAgentParser) {
this.userAgentParser = userAgentParser;
}
}

View File

@ -27,6 +27,7 @@ import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
import cn.topiam.employee.support.security.web.AbstractAuthenticationEntryPoint;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@ -43,6 +44,10 @@ import static cn.topiam.eiam.protocol.oidc.constant.OidcProtocolConstants.OIDC_E
*/
public class ClientAuthenticationRequiredEntryPoint extends AbstractAuthenticationEntryPoint {
public ClientAuthenticationRequiredEntryPoint(UserAgentParser userAgentParser) {
super(userAgentParser);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException,

View File

@ -52,6 +52,7 @@ import cn.topiam.employee.common.constant.ProtocolConstants;
import cn.topiam.employee.protocol.code.EndpointMatcher;
import cn.topiam.employee.protocol.code.UnauthorizedAuthenticationEntryPoint;
import cn.topiam.employee.protocol.code.configurer.AbstractConfigurer;
import cn.topiam.employee.support.web.useragent.UserAgentParser;
import static cn.topiam.employee.protocol.code.configurer.AuthenticationUtils.getApplicationServiceLoader;
import static cn.topiam.employee.support.security.util.HttpSecurityConfigUtils.getOptionalBean;
@ -97,10 +98,10 @@ public final class OAuth2AuthorizationServerConfigurer extends
if (exceptionHandling != null) {
//认证端点异常
exceptionHandling.defaultAuthenticationEntryPointFor(
new UnauthorizedAuthenticationEntryPoint(), new OrRequestMatcher(
new UnauthorizedAuthenticationEntryPoint(userAgentParser), new OrRequestMatcher(
getRequestMatcher(OAuth2AuthorizationEndpointConfigurer.class)));
exceptionHandling.defaultAuthenticationEntryPointFor(
new ClientAuthenticationRequiredEntryPoint(),
new ClientAuthenticationRequiredEntryPoint(userAgentParser),
new OrRequestMatcher(getRequestMatcher(OAuth2TokenEndpointConfigurer.class),
getRequestMatcher(OAuth2TokenIntrospectionEndpointConfigurer.class),
getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class),
@ -200,4 +201,9 @@ public final class OAuth2AuthorizationServerConfigurer extends
return configurers;
}
private final UserAgentParser userAgentParser;
public OAuth2AuthorizationServerConfigurer(UserAgentParser userAgentParser) {
this.userAgentParser = userAgentParser;
}
}

View File

@ -68,7 +68,8 @@ import cn.topiam.employee.support.trace.TraceUtils;
import cn.topiam.employee.synchronizer.task.IdentitySourceSyncTask;
import lombok.extern.slf4j.Slf4j;
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
import static cn.topiam.employee.support.constant.EiamConstants.CACHE_LOCK_KEY_PREFIX;
import static cn.topiam.employee.support.constant.EiamConstants.COLON;
import static cn.topiam.employee.synchronizer.configuration.IdentitySourceBeanUtils.getSourceBeanName;
/**
@ -305,7 +306,7 @@ public class IdentitySourceBeanRegistry implements IdentitySourceEventListener {
stopWatch.start();
log.info("[手动任务]-同步身份源[{}]数据开始", identitySource.getName());
TraceUtils.put(new JdkIdGenerator().generateId().toString());
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix() + id);
RLock lock = redissonClient.getLock(CACHE_LOCK_KEY_PREFIX + COLON + id);
boolean tryLock = false;
try {
tryLock = lock.tryLock(1, TimeUnit.SECONDS);

View File

@ -32,7 +32,8 @@ import cn.topiam.employee.identitysource.core.IdentitySourceConfig;
import cn.topiam.employee.support.trace.TraceUtils;
import lombok.RequiredArgsConstructor;
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
import static cn.topiam.employee.support.constant.EiamConstants.CACHE_LOCK_KEY_PREFIX;
import static cn.topiam.employee.support.constant.EiamConstants.COLON;
/**
*
@ -64,7 +65,7 @@ public class IdentitySourceSyncTask implements Runnable {
logger.info("[任务触发]-同步身份源[{}]数据开始", name);
String traceId = idGenerator.generateId().toString();
TraceUtils.put(traceId);
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix() + id);
RLock lock = redissonClient.getLock(CACHE_LOCK_KEY_PREFIX + COLON + id);
boolean tryLock = false;
try {
tryLock = lock.tryLock(1, TimeUnit.SECONDS);