@@ -8,14 +8,14 @@ import java.util.Collections; | |||||
/** | /** | ||||
* @description: 自动生成code代码 | * @description: 自动生成code代码 | ||||
* @author: liushuai | |||||
* @date: 2022/3/25 14:20 | |||||
* @author: liuxinxin | |||||
* @date: 2023/01/03 09:20 | |||||
*/ | */ | ||||
public class GeneratorCodeConfig { | public class GeneratorCodeConfig { | ||||
private static final String PATH_LXX = "/Users/liuxinxin/IdeaProjects/car_rental/ningda-car-rental-api/src/main/java"; | |||||
private static final String PATH_YYD = "/Users/wendy/code project/java/car_rental/ningda-car-rental-api/src/main/java"; | |||||
private static final String PATH_LS = "/Users/qinxianyun/Documents/qin/ningdatech/car_rental/ningda-car-rental-api/src/main/java"; | |||||
private static final String PATH_LXX = ""; | |||||
private static final String PATH_YYD = ""; | |||||
private static final String PATH_LS = ""; | |||||
private static final String PATH_ZPF = ""; | private static final String PATH_ZPF = ""; | ||||
private static final String PATH_CMM = ""; | private static final String PATH_CMM = ""; | ||||
@@ -41,11 +41,11 @@ public class GeneratorCodeConfig { | |||||
// 设置父包名 | // 设置父包名 | ||||
builder.parent("com.ningdatech") | builder.parent("com.ningdatech") | ||||
// 设置父包模块名 | // 设置父包模块名 | ||||
.moduleName("rentalcar." + packageName) | |||||
.moduleName("pmapi." + packageName) | |||||
// 设置mapperXml生成路径 | // 设置mapperXml生成路径 | ||||
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, | .pathInfo(Collections.singletonMap(OutputFile.mapperXml, | ||||
//设置自己的生成路径 | //设置自己的生成路径 | ||||
path + "/com/ningdatech/rentalcar/" + packageName + "/mapper")); | |||||
path + "/com/ningdatech/pmapi/" + packageName + "/mapper")); | |||||
}) | }) | ||||
.strategyConfig(builder -> { | .strategyConfig(builder -> { | ||||
builder.addTablePrefix("nd"); | builder.addTablePrefix("nd"); | ||||
@@ -58,7 +58,7 @@ public class GeneratorCodeConfig { | |||||
} | } | ||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
generate("Liuxinxin", "order", PATH_YYD, "nd_order_status_change"); | |||||
generate("Liuxinxin", "null", PATH_LXX, "null"); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,98 @@ | |||||
package com.ningdatech.pmapi.common.constants; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import java.math.BigDecimal; | |||||
/** | |||||
* <p> | |||||
* 业务常量 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 13:42 2022/12/1 | |||||
*/ | |||||
public interface BizConst { | |||||
/** | |||||
* SQL查询一条 | |||||
*/ | |||||
String LIMIT_1 = "limit 1"; | |||||
String COOKIE_KEY = "ND_CAR_RENTAL_JSESSION"; | |||||
/** | |||||
* 一小时秒数 | |||||
**/ | |||||
BigDecimal SECONDS_BY_HOUR = new BigDecimal(60 * 60); | |||||
/** | |||||
* 十分钟的毫秒数 | |||||
*/ | |||||
long MILLS_10_MIN = 1000L * 60 * 10; | |||||
/** | |||||
* 中国行政区划编码 | |||||
*/ | |||||
long ROOT_REGION_CODE = 100000L; | |||||
/** | |||||
* 一级行政区划数量 | |||||
*/ | |||||
int NUM_PROVINCE = 34; | |||||
/** | |||||
* 默认的父id | |||||
*/ | |||||
long PARENT_ID = 0L; | |||||
/** | |||||
* 默认树层级 | |||||
*/ | |||||
int TREE_GRADE = 0; | |||||
/** | |||||
* 默认的排序 | |||||
*/ | |||||
int SORT_VALUE = 0; | |||||
/** | |||||
* 浙江省的region_id | |||||
*/ | |||||
long ZJ_REGION_CODE = 330000L; | |||||
/** | |||||
* 省/直辖市 level | |||||
*/ | |||||
int GOV_L1 = 1; | |||||
/** | |||||
* 市 level | |||||
*/ | |||||
int GOV_L2 = 2; | |||||
/** | |||||
* 区/县 level | |||||
*/ | |||||
int GOV_L3 = 3; | |||||
/** | |||||
* 密码正则:长度8-20位且至少包含大写字母、小写字母、数字或特殊符号中的任意三种 | |||||
*/ | |||||
String REGEX_PASS = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,20}$"; | |||||
/** | |||||
* 租车费率 | |||||
*/ | |||||
BigDecimal RATE_CAR_RENTAL = new BigDecimal("1.13"); | |||||
/** | |||||
* 服务费率 | |||||
*/ | |||||
BigDecimal RATE_SERVICE = new BigDecimal("0.0442"); | |||||
ApiResponse<Void> UNAUTHENTICATED = ApiResponse.of(401, "用户未登录", null); | |||||
int MAX_EXPORT_COUNT = 5000; | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package com.ningdatech.pmapi.common.errorcode; | |||||
public enum AppErrorCode { | |||||
USER(100), | |||||
AUTH(101); | |||||
private final Integer code; | |||||
AppErrorCode(Integer code) { | |||||
this.code = code; | |||||
} | |||||
public Integer getCode() { | |||||
return code; | |||||
} | |||||
} |
@@ -0,0 +1,62 @@ | |||||
package com.ningdatech.pmapi.common.handler; | |||||
import com.ningdatech.basic.enumeration.Status; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.context.support.DefaultMessageSourceResolvable; | |||||
import org.springframework.http.HttpStatus; | |||||
import org.springframework.validation.BindException; | |||||
import org.springframework.web.bind.MethodArgumentNotValidException; | |||||
import org.springframework.web.bind.annotation.ControllerAdvice; | |||||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
import org.springframework.web.bind.annotation.ResponseBody; | |||||
import org.springframework.web.bind.annotation.ResponseStatus; | |||||
import org.springframework.web.servlet.NoHandlerFoundException; | |||||
import javax.validation.ConstraintViolation; | |||||
import javax.validation.ConstraintViolationException; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* @description: 统一错误处理 | |||||
* @author: liuxinxin | |||||
* @date: 2023/01/03 11:39 | |||||
*/ | |||||
@Slf4j | |||||
@ControllerAdvice | |||||
@ResponseStatus(HttpStatus.BAD_REQUEST) | |||||
public class GlobalExceptionHandler { | |||||
@ResponseBody | |||||
@ExceptionHandler(value = NoHandlerFoundException.class) | |||||
public ApiResponse<Void> noHandlerFoundException(NoHandlerFoundException e) { | |||||
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", e.getRequestURL(), e.getHttpMethod()); | |||||
return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class}) | |||||
public ApiResponse<Void> bindException(BindException e) { | |||||
String msg = e.getAllErrors().stream() | |||||
.map(DefaultMessageSourceResolvable::getDefaultMessage) | |||||
.collect(Collectors.joining(",")); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = ConstraintViolationException.class) | |||||
public ApiResponse<Void> constraintViolationException(ConstraintViolationException e) { | |||||
String msg = e.getConstraintViolations().stream() | |||||
.map(ConstraintViolation::getMessage) | |||||
.collect(Collectors.joining(",")); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), msg, null); | |||||
} | |||||
@ResponseBody | |||||
@ExceptionHandler(value = Exception.class) | |||||
public ApiResponse<Void> handlerException(Exception e) { | |||||
log.error("【全局异常拦截】: 异常信息 {}: {} ", e.getClass().getSimpleName(), e); | |||||
return ApiResponse.of(Status.BAD_REQUEST.getCode(), e.getMessage(), null); | |||||
} | |||||
} |
@@ -0,0 +1,56 @@ | |||||
package com.ningdatech.pmapi.common.handler; | |||||
import cn.hutool.json.JSONUtil; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import org.springframework.core.MethodParameter; | |||||
import org.springframework.http.MediaType; | |||||
import org.springframework.http.converter.HttpMessageConverter; | |||||
import org.springframework.http.server.ServerHttpRequest; | |||||
import org.springframework.http.server.ServerHttpResponse; | |||||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
import org.springframework.web.bind.annotation.RestControllerAdvice; | |||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | |||||
/** | |||||
* @Author liuxinxin | |||||
* @Date 2021/7/21 11:26 | |||||
* @Version 1.0 | |||||
**/ | |||||
@RestControllerAdvice(basePackages = {}) | |||||
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | |||||
private static final String SWAGGER_CLASS_PREFIX = "springfox.documentation"; | |||||
@Override | |||||
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { | |||||
return filter(methodParameter); | |||||
} | |||||
@Override | |||||
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, | |||||
Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, | |||||
ServerHttpResponse serverHttpResponse) { | |||||
ApiResponse<Object> apiResponse = ApiResponse.ofSuccess(o); | |||||
// 处理字符串时,遇到了类型转换的问题,debug一步一步跟踪,原来是对于字符串的ContentType是“text-plain”, | |||||
// ConverterType是StringHttpMessageConverter这个类型转换, | |||||
// 由于将结果封装成了自定义的ApiResponse类型,所以有ApiResponse转换成String报错 | |||||
// 所以需要对String类型的返回值单独进行处理 | |||||
if (o instanceof String) { | |||||
return JSONUtil.toJsonStr(apiResponse); | |||||
} | |||||
return ApiResponse.ofSuccess(o); | |||||
} | |||||
private Boolean filter(MethodParameter methodParameter) { | |||||
Class<?> declaringClass = methodParameter.getDeclaringClass(); | |||||
// swagger中的所有返回不进行统一封装 | |||||
if (declaringClass.getName().contains(SWAGGER_CLASS_PREFIX)) { | |||||
return false; | |||||
} | |||||
if (methodParameter.hasMethodAnnotation(ExceptionHandler.class)) { | |||||
return false; | |||||
} | |||||
// 如果本身就是使用ApiResponse返回,则不需要进行格式化 | |||||
return !methodParameter.getParameterType().equals(ApiResponse.class); | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
package com.ningdatech.pmapi.user.manage; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2023/1/3 上午10:57 | |||||
*/ | |||||
@Component | |||||
public class UserAuthLoginManage { | |||||
} |
@@ -0,0 +1,97 @@ | |||||
package com.ningdatech.pmapi.user.security.auth; | |||||
import com.ningdatech.basic.util.NdJsonUtil; | |||||
import com.ningdatech.basic.util.StrPool; | |||||
import com.ningdatech.pmapi.common.constants.BizConst; | |||||
import com.ningdatech.pmapi.user.security.auth.config.AuthProperties; | |||||
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; | |||||
import com.ningdatech.pmapi.user.security.auth.password.UsernamePasswordAuthSecurityConfig; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.http.HttpStatus; | |||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |||||
import org.springframework.security.web.AuthenticationEntryPoint; | |||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | |||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository; | |||||
import java.io.PrintWriter; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/7/28 4:14 下午 | |||||
* @Version 1.0 | |||||
*/ | |||||
@Configuration | |||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||||
private final AuthProperties authProperties; | |||||
private final UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig; | |||||
private final LogoutSuccessHandler logoutSuccessHandler; | |||||
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | |||||
public WebSecurityConfig(AuthProperties authProperties, | |||||
UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig, | |||||
@Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler, | |||||
DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) { | |||||
this.authProperties = authProperties; | |||||
this.usernamePasswordAuthSecurityConfig = usernamePasswordAuthSecurityConfig; | |||||
this.logoutSuccessHandler = logoutSuccessHandler; | |||||
this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy; | |||||
} | |||||
@Override | |||||
protected void configure(HttpSecurity http) throws Exception { | |||||
assemblerPreAuthUrls(http); | |||||
http.formLogin() | |||||
.and() | |||||
.exceptionHandling() | |||||
.authenticationEntryPoint(authenticationEntryPoint()) | |||||
.and().apply(usernamePasswordAuthSecurityConfig) | |||||
.and() | |||||
.authorizeRequests() | |||||
.antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll() | |||||
.anyRequest() | |||||
.authenticated() | |||||
.and() | |||||
// 防止固定会话攻击,Spring security的默认配置就是如此: | |||||
// 登陆成功之后会创建一个新的会话,然后将旧的session信息复制到新的session中(客户端的sessionId变了) | |||||
.sessionManagement().invalidSessionUrl(authProperties.getInvalidSessionUrl()).sessionFixation() | |||||
.migrateSession() | |||||
// .invalidSessionStrategy(defaultInvalidSessionStrategy) | |||||
.maximumSessions(10).maxSessionsPreventsLogin(true).expiredSessionStrategy(defaultExpiredSessionStrategy) | |||||
.and().and().logout().logoutUrl(authProperties.getLogoutUrl()).logoutSuccessHandler(logoutSuccessHandler) | |||||
.deleteCookies(BizConst.COOKIE_KEY) | |||||
.and() | |||||
// 开启csrf验证,需要前端同步传入token | |||||
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) | |||||
.ignoringAntMatchers(authProperties.getIgnoreCsrfUrlsArray()); | |||||
} | |||||
private AuthenticationEntryPoint authenticationEntryPoint() { | |||||
return (request, response, authException) -> { | |||||
response.setContentType(StrPool.CONTENT_TYPE); | |||||
response.setStatus(HttpStatus.UNAUTHORIZED.value()); | |||||
PrintWriter writer = response.getWriter(); | |||||
writer.write(NdJsonUtil.getInstance().writeValueAsString(BizConst.UNAUTHENTICATED)); | |||||
writer.flush(); | |||||
writer.close(); | |||||
}; | |||||
} | |||||
private void assemblerPreAuthUrls(HttpSecurity http) throws Exception { | |||||
Map<String, String[]> roleArrayMap = authProperties.getRoleArrayMap(); | |||||
Set<String> roleSet = roleArrayMap.keySet(); | |||||
for (String role : roleSet) { | |||||
String[] urlsArray = roleArrayMap.get(role); | |||||
if (urlsArray != null && urlsArray.length > 0) { | |||||
http.authorizeRequests().antMatchers(urlsArray).hasAuthority(role); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.config; | |||||
import cn.hutool.core.collection.CollectionUtil; | |||||
import com.ningdatech.basic.factory.PropertySourceFactory; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.context.annotation.PropertySource; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.*; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/1 6:06 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
@Configuration | |||||
@PropertySource(value = "classpath:security/auth-${spring.profiles.active}.yml" | |||||
, encoding = "utf-8", factory = PropertySourceFactory.class) | |||||
@ConfigurationProperties(prefix = "security.auth") | |||||
@Component | |||||
@Data | |||||
public class AuthProperties { | |||||
private String authRequireUrl; | |||||
private String invalidSessionUrl; | |||||
private String passwordLoginUrl; | |||||
private String logoutUrl; | |||||
private List<String> ignoreAuthUrls; | |||||
private List<String> ignoreCsrfUrls; | |||||
private Map<String, List<String>> roleMap = new HashMap<>(); | |||||
public String[] getIgnoreAuthUrlsArray() { | |||||
String[] stringArray = new String[ignoreAuthUrls.size()]; | |||||
return ignoreAuthUrls.toArray(stringArray); | |||||
} | |||||
public String[] getIgnoreCsrfUrlsArray() { | |||||
String[] stringArray = new String[ignoreCsrfUrls.size()]; | |||||
return ignoreCsrfUrls.toArray(stringArray); | |||||
} | |||||
public Map<String, String[]> getRoleArrayMap() { | |||||
Map<String, String[]> roleArrayMap = new HashMap<>(); | |||||
if (Objects.nonNull(roleMap)) { | |||||
Set<String> keySet = roleMap.keySet(); | |||||
for (String key : keySet) { | |||||
List<String> urls = roleMap.get(key); | |||||
if (CollectionUtil.isNotEmpty(urls)) { | |||||
String[] stringArray = new String[urls.size()]; | |||||
roleArrayMap.put(key, urls.toArray(stringArray)); | |||||
} | |||||
} | |||||
} | |||||
return roleArrayMap; | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.config; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.security.core.session.SessionRegistry; | |||||
import org.springframework.security.core.session.SessionRegistryImpl; | |||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||||
import org.springframework.security.crypto.password.PasswordEncoder; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/7/28 1:00 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
@Configuration | |||||
public class AuthenticationBeanConfig { | |||||
@Bean | |||||
public PasswordEncoder passwordEncoder() { | |||||
return new BCryptPasswordEncoder(); | |||||
} | |||||
@Bean | |||||
public SessionRegistry sessionRegistry() { | |||||
return new SessionRegistryImpl(); | |||||
} | |||||
} |
@@ -0,0 +1,49 @@ | |||||
//package com.ningdatech.pmapi.user.security.auth.config; | |||||
// | |||||
//import com.ningdatech.basic.util.StrPool; | |||||
//import org.springframework.beans.factory.annotation.Value; | |||||
//import org.springframework.context.annotation.Bean; | |||||
//import org.springframework.context.annotation.Configuration; | |||||
// | |||||
///** | |||||
// * <p> | |||||
// * 设置session的过期时间为一天 | |||||
// * </p> | |||||
// * | |||||
// * @Author LiuXinXin | |||||
// * @Date 2020/7/29 9:46 上午 | |||||
// * @Version 1.0 | |||||
// **/ | |||||
//@Configuration | |||||
//@EnableRedisHttpSession( | |||||
// maxInactiveIntervalInSeconds = RedisSessionConfig.SESSION_TIMEOUT, | |||||
// redisNamespace = RedisSessionConfig.REDIS_NAMESPACE | |||||
//) | |||||
//public class RedisSessionConfig { | |||||
// | |||||
// static final int SESSION_TIMEOUT = 24 * 60 * 60 * 10; | |||||
// | |||||
// static final String REDIS_NAMESPACE = "#{redisSessionConfig.getRedisNamespace()}"; | |||||
// | |||||
// @Value("${nd.cache.def.keyPrefix:}") | |||||
// private String keyPrefix; | |||||
// | |||||
// public String getRedisNamespace() { | |||||
// return (StrUtils.isBlank(keyPrefix) ? StrPool.EMPTY : keyPrefix + StrPool.COLON) + RedisIndexedSessionRepository.DEFAULT_NAMESPACE; | |||||
// } | |||||
// | |||||
// @Bean | |||||
// public CookieHttpSessionIdResolver sessionIdResolver() { | |||||
// // 创建 CookieHttpSessionIdResolver 对象 | |||||
// CookieHttpSessionIdResolver sessionIdResolver = new CookieHttpSessionIdResolver(); | |||||
// // 创建 DefaultCookieSerializer 对象 | |||||
// DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); | |||||
// | |||||
// // 设置到 sessionIdResolver 中 | |||||
// sessionIdResolver.setCookieSerializer(cookieSerializer); | |||||
// cookieSerializer.setCookieName(BizConst.COOKIE_KEY); | |||||
// cookieSerializer.setCookieMaxAge(SessionTimeConstant.SESSION_TIME_SECONDS); | |||||
// return sessionIdResolver; | |||||
// } | |||||
// | |||||
//} |
@@ -0,0 +1,47 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.constants; | |||||
/** | |||||
* @author Liuxinxin | |||||
* @date 2021/7/30 下午2:10 | |||||
*/ | |||||
public enum AuthTypeEnum { | |||||
/** | |||||
* 手机 + 密码的认证方式 | |||||
*/ | |||||
PHONE_PASSWORD("phone_password"), | |||||
/** | |||||
* 子账号 账号 + 密码的认证方式 | |||||
*/ | |||||
ACCOUNT_PASSWORD("account_password"); | |||||
private final String key; | |||||
AuthTypeEnum(String key) { | |||||
this.key = key; | |||||
} | |||||
public static boolean contains(String key) { | |||||
for (AuthTypeEnum value : AuthTypeEnum.values()) { | |||||
if (key.equals(value.getKey())) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
public String getKey() { | |||||
return key; | |||||
} | |||||
public static AuthTypeEnum of(String key) { | |||||
for (AuthTypeEnum value : AuthTypeEnum.values()) { | |||||
if (key.equals(value.getKey())) { | |||||
return value; | |||||
} | |||||
} | |||||
throw new RuntimeException(String.format("invalid AuthTypeEnum = %s", key)); | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.constants; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2022/2/17 12:59 上午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class SessionTimeConstant { | |||||
public static final Integer SESSION_TIME_SECONDS = 24 * 60 * 60 * 10; | |||||
} |
@@ -0,0 +1,34 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.errorcode; | |||||
import com.ningdatech.pmapi.common.errorcode.AppErrorCode; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2021/7/30 上午10:59 | |||||
*/ | |||||
@AllArgsConstructor | |||||
@Getter | |||||
public enum AuthErrorCodeEnum { | |||||
USERNAME_OR_PASSWORD_ERROR(AppErrorCode.AUTH.getCode() + "100000" | |||||
, "登陆时用户名或者密码错误"), | |||||
ACCOUNT_ALREADY_EXIST_WHEN_REGISTER(AppErrorCode.AUTH.getCode() + "100001" | |||||
, "账号已经存在"), | |||||
SESSION_EXPIRED(AppErrorCode.AUTH.getCode() + "100002" | |||||
, "用户session过期,登陆状态失效"); | |||||
private final String code; | |||||
private final String msg; | |||||
public Integer getCode() { | |||||
return Integer.valueOf(code); | |||||
} | |||||
} |
@@ -0,0 +1,41 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.handler; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import com.ningdatech.pmapi.user.security.auth.errorcode.AuthErrorCodeEnum; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.security.web.session.SessionInformationExpiredEvent; | |||||
import org.springframework.security.web.session.SessionInformationExpiredStrategy; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.ServletException; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/20 11:15 上午 | |||||
* @Version 1.0 | |||||
**/ | |||||
@Component | |||||
public class DefaultExpiredSessionStrategy implements SessionInformationExpiredStrategy { | |||||
public static final Logger LOG = LoggerFactory.getLogger(DefaultExpiredSessionStrategy.class); | |||||
@Autowired | |||||
private ObjectMapper objectMapper; | |||||
@Override | |||||
public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) | |||||
throws IOException, ServletException { | |||||
if (LOG.isInfoEnabled()) { | |||||
LOG.info("session is expired"); | |||||
} | |||||
HttpServletResponse response = sessionInformationExpiredEvent.getResponse(); | |||||
response.setContentType("application/json;charset=UTF-8"); | |||||
response.getWriter().write(objectMapper.writeValueAsString( | |||||
ApiResponse.of(AuthErrorCodeEnum.SESSION_EXPIRED.getCode(), AuthErrorCodeEnum.SESSION_EXPIRED.getMsg(), null))); | |||||
} | |||||
} |
@@ -0,0 +1,47 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.handler; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import com.ningdatech.pmapi.user.security.auth.errorcode.AuthErrorCodeEnum; | |||||
import org.springframework.security.authentication.BadCredentialsException; | |||||
import org.springframework.security.core.AuthenticationException; | |||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.ServletException; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:32 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
@Component("defaultLoginFailureHandler") | |||||
public class DefaultLoginFailureHandler extends SimpleUrlAuthenticationFailureHandler { | |||||
private final ObjectMapper objectMapper = new ObjectMapper(); | |||||
@Override | |||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, | |||||
AuthenticationException exception) throws IOException, ServletException { | |||||
response.setContentType("application/json;charset=UTF-8"); | |||||
int errorCode; | |||||
String errorMsg; | |||||
// 所有的认证异常都可以在这里添加,目前只支持用户名密码错误异常 | |||||
if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) { | |||||
errorCode = AuthErrorCodeEnum.USERNAME_OR_PASSWORD_ERROR.getCode(); | |||||
errorMsg = exception.getMessage(); | |||||
} else { | |||||
errorCode = ApiResponse.ERROR_CODE; | |||||
errorMsg = ApiResponse.ERROR_MSG; | |||||
} | |||||
response.setStatus(400); | |||||
response.getWriter() | |||||
.write(objectMapper.writeValueAsString(ApiResponse.of(errorCode, errorMsg, null))); | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.handler; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.context.annotation.Primary; | |||||
import org.springframework.http.MediaType; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:32 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
@Component("defaultLoginSuccessHandler") | |||||
@Primary | |||||
public class DefaultLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { | |||||
@Autowired | |||||
private ObjectMapper objectMapper; | |||||
@Override | |||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, | |||||
Authentication authentication) throws IOException { | |||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | |||||
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess())); | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.handler; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | |||||
/** | |||||
* 默认的退出成功处理器 | |||||
*/ | |||||
@Component("defaultLogoutSuccessHandler") | |||||
public class DefaultLogoutSuccessHandler implements LogoutSuccessHandler { | |||||
private final ObjectMapper objectMapper = new ObjectMapper(); | |||||
@Override | |||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) | |||||
throws IOException { | |||||
// 退出成功后返回 和前端约定的Json | |||||
response.setContentType("application/json;charset=UTF-8"); | |||||
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess())); | |||||
} | |||||
} |
@@ -0,0 +1,81 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.model; | |||||
import cn.hutool.core.collection.CollectionUtil; | |||||
import com.ningdatech.basic.auth.AbstractLoginUser; | |||||
import lombok.Data; | |||||
import lombok.EqualsAndHashCode; | |||||
import org.springframework.security.core.GrantedAuthority; | |||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | |||||
import org.springframework.security.core.userdetails.UserDetails; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2022/8/1 下午3:32 | |||||
*/ | |||||
@Data | |||||
@EqualsAndHashCode(callSuper = true) | |||||
public class UserInfoDetails extends AbstractLoginUser implements UserDetails { | |||||
private String realName; | |||||
private String password; | |||||
private String role; | |||||
/** | |||||
* 区域code | |||||
*/ | |||||
private Long regionCode; | |||||
private Long companyId; | |||||
/** | |||||
* 所负责公司id列表 | |||||
*/ | |||||
private List<Long> responsibleCompanyIdList; | |||||
/** | |||||
* 获取用户权限 | |||||
* | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public Collection<? extends GrantedAuthority> getAuthorities() { | |||||
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(this.role); | |||||
return CollectionUtil.toList(simpleGrantedAuthority); | |||||
} | |||||
@Override | |||||
public String getPassword() { | |||||
return password; | |||||
} | |||||
@Override | |||||
public String getUsername() { | |||||
return getIdentifier(); | |||||
} | |||||
@Override | |||||
public boolean isAccountNonExpired() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isAccountNonLocked() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isCredentialsNonExpired() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isEnabled() { | |||||
return true; | |||||
} | |||||
} |
@@ -0,0 +1,41 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | |||||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||||
import lombok.RequiredArgsConstructor; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||||
import org.springframework.stereotype.Service; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2022/9/30 上午9:49 | |||||
*/ | |||||
@Service("passwordLoginUserDetailService") | |||||
@RequiredArgsConstructor | |||||
public class PasswordLoginUserDetailService implements UserDetailsService { | |||||
private final UserAuthLoginManage userAuthLoginManage; | |||||
@Override | |||||
public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||||
// UserFullInfoDTO userFullInfoDTO = userAuthLoginFacade.queryUserInfoInPasswordAuth(username); | |||||
// if (Objects.isNull(userFullInfoDTO)) { | |||||
// throw new UsernameNotFoundException(String.format("%s user not exist", username)); | |||||
// } | |||||
// UserInfoDetails userInfoDetails = new UserInfoDetails(); | |||||
// userInfoDetails.setUserId(userFullInfoDTO.getUserId()); | |||||
// userInfoDetails.setUsername(userFullInfoDTO.getUsername()); | |||||
// userInfoDetails.setRealName(userFullInfoDTO.getRealName()); | |||||
// userInfoDetails.setRole(userFullInfoDTO.getRole()); | |||||
// userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode()); | |||||
// userInfoDetails.setCompanyId(userFullInfoDTO.getCompanyId()); | |||||
// userInfoDetails.setResponsibleCompanyIdList(userFullInfoDTO.getResponsibleCompanyIdList()); | |||||
// userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); | |||||
// userInfoDetails.setPassword(userFullInfoDTO.getCredential()); | |||||
// return userInfoDetails; | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,71 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
import com.ningdatech.basic.exception.BizException; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.http.HttpMethod; | |||||
import org.springframework.security.authentication.AuthenticationServiceException; | |||||
import org.springframework.security.authentication.BadCredentialsException; | |||||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.core.AuthenticationException; | |||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | |||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:46 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class UsernamePasswordAuthFilter extends AbstractAuthenticationProcessingFilter { | |||||
private boolean postOnly = true; | |||||
private static final String USERNAME_PARAMETER = "username"; | |||||
private static final String PASSWORD_PARAMETER = "password"; | |||||
// ~ Constructors | |||||
// =================================================================================================== | |||||
public UsernamePasswordAuthFilter(String processingUrl) { | |||||
super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name())); | |||||
} | |||||
// ~ Methods | |||||
// ======================================================================================================== | |||||
@Override | |||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) | |||||
throws AuthenticationException { | |||||
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { | |||||
throw new AuthenticationServiceException("请求方法错误"); | |||||
} | |||||
String username = request.getParameter(USERNAME_PARAMETER); | |||||
String password = request.getParameter(PASSWORD_PARAMETER); | |||||
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { | |||||
throw new UsernameNotFoundException("用户名或密码不能为空"); | |||||
} | |||||
username = username.trim(); | |||||
password = password.trim(); | |||||
try { | |||||
UsernamePasswordAuthToken authRequest = new UsernamePasswordAuthToken(username, password); | |||||
// Allow subclasses to set the "details" property | |||||
setDetails(request, authRequest); | |||||
return this.getAuthenticationManager().authenticate(authRequest); | |||||
} catch (AuthenticationException e) { | |||||
throw new BadCredentialsException("账号或密码错误"); | |||||
} catch (BizException e) { | |||||
throw new BadCredentialsException(e.getMessage()); | |||||
} catch (Exception e) { | |||||
throw new InternalAuthenticationServiceException("授权失败:", e); | |||||
} | |||||
} | |||||
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthToken authRequest) { | |||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
import org.springframework.security.authentication.AuthenticationProvider; | |||||
import org.springframework.security.authentication.BadCredentialsException; | |||||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | |||||
import org.springframework.security.core.Authentication; | |||||
import org.springframework.security.core.AuthenticationException; | |||||
import org.springframework.security.core.userdetails.UserDetails; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.crypto.password.PasswordEncoder; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:55 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class UsernamePasswordAuthProvider implements AuthenticationProvider { | |||||
private UserDetailsService userDetailsService; | |||||
private PasswordEncoder passwordEncoder; | |||||
@Override | |||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | |||||
if (!(authentication instanceof UsernamePasswordAuthToken)) { | |||||
throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); | |||||
} | |||||
UsernamePasswordAuthToken authenticationToken = (UsernamePasswordAuthToken) authentication; | |||||
UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); | |||||
if (user == null) { | |||||
throw new InternalAuthenticationServiceException("can not get user info!"); | |||||
} | |||||
additionalAuthenticationChecks(user, authenticationToken); | |||||
// 校验用户是否有当前端的登陆权限 | |||||
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | |||||
return new UsernamePasswordAuthToken(user, user.getPassword(), user.getAuthorities()); | |||||
} | |||||
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthToken authentication) | |||||
throws AuthenticationException { | |||||
if (authentication.getCredentials() == null) { | |||||
throw new BadCredentialsException("login fail! password is null"); | |||||
} | |||||
String presentedPassword = authentication.getCredentials().toString(); | |||||
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { | |||||
throw new BadCredentialsException("login fail! password is error"); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean supports(Class<?> authentication) { | |||||
return UsernamePasswordAuthToken.class.isAssignableFrom(authentication); | |||||
} | |||||
public void setUserDetailsService(UserDetailsService userDetailsService) { | |||||
this.userDetailsService = userDetailsService; | |||||
} | |||||
public void setPasswordEncoder(PasswordEncoder passwordEncoder) { | |||||
this.passwordEncoder = passwordEncoder; | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
import com.ningdatech.pmapi.user.security.auth.config.AuthProperties; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | |||||
import org.springframework.security.authentication.AuthenticationManager; | |||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; | |||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||||
import org.springframework.security.core.userdetails.UserDetailsService; | |||||
import org.springframework.security.crypto.password.PasswordEncoder; | |||||
import org.springframework.security.web.DefaultSecurityFilterChain; | |||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* 账号密码登陆的认证配置 | |||||
*/ | |||||
@Component | |||||
public class UsernamePasswordAuthSecurityConfig | |||||
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | |||||
@Autowired | |||||
@Qualifier(value = "defaultLoginSuccessHandler") | |||||
protected AuthenticationSuccessHandler defaultLoginSuccessHandler; | |||||
@Autowired | |||||
@Qualifier(value = "defaultLoginFailureHandler") | |||||
protected AuthenticationFailureHandler defaultLoginFailureHandler; | |||||
@Autowired | |||||
@Qualifier(value = "passwordLoginUserDetailService") | |||||
private UserDetailsService passwordLoginUserDetailService; | |||||
@Autowired | |||||
private PasswordEncoder passwordEncoder; | |||||
@Autowired | |||||
private AuthProperties authProperties; | |||||
private AuthenticationManager authenticationManager; | |||||
@Override | |||||
public void configure(HttpSecurity http) throws Exception { | |||||
UsernamePasswordAuthFilter usernamePasswordAuthFilter = | |||||
new UsernamePasswordAuthFilter(authProperties.getPasswordLoginUrl()); | |||||
authenticationManager = http.getSharedObject(AuthenticationManager.class); | |||||
usernamePasswordAuthFilter.setAuthenticationManager(authenticationManager); | |||||
usernamePasswordAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); | |||||
usernamePasswordAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | |||||
UsernamePasswordAuthProvider authenticationProvider = new UsernamePasswordAuthProvider(); | |||||
authenticationProvider.setUserDetailsService(passwordLoginUserDetailService); | |||||
// 确保对密码进行加密的encoder和解密的encoder相同 | |||||
authenticationProvider.setPasswordEncoder(passwordEncoder); | |||||
http.authenticationProvider(authenticationProvider).addFilterAfter(usernamePasswordAuthFilter, | |||||
UsernamePasswordAuthenticationFilter.class); | |||||
} | |||||
public AuthenticationManager getAuthenticationManager() { | |||||
return authenticationManager; | |||||
} | |||||
} |
@@ -0,0 +1,76 @@ | |||||
package com.ningdatech.pmapi.user.security.auth.password; | |||||
import org.springframework.security.authentication.AbstractAuthenticationToken; | |||||
import org.springframework.security.core.GrantedAuthority; | |||||
import org.springframework.security.core.SpringSecurityCoreVersion; | |||||
import java.util.Collection; | |||||
/** | |||||
* @Author LiuXinXin | |||||
* @Date 2020/8/3 8:52 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class UsernamePasswordAuthToken extends AbstractAuthenticationToken { | |||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | |||||
private final Object principal; | |||||
private final Object credentials; | |||||
/** | |||||
* This constructor can be safely used by any code that wishes to create a | |||||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return | |||||
* <code>false</code>. | |||||
*/ | |||||
public UsernamePasswordAuthToken(String principal, String credentials) { | |||||
super(null); | |||||
this.principal = principal; | |||||
this.credentials = credentials; | |||||
setAuthenticated(false); | |||||
} | |||||
/** | |||||
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code> | |||||
* implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>) | |||||
* authentication token. | |||||
* | |||||
* @param principal | |||||
* @param authorities | |||||
*/ | |||||
public UsernamePasswordAuthToken(Object principal, Object credentials, | |||||
Collection<? extends GrantedAuthority> authorities) { | |||||
super(authorities); | |||||
this.principal = principal; | |||||
this.credentials = credentials; | |||||
// must use super, as we override | |||||
super.setAuthenticated(true); | |||||
} | |||||
@Override | |||||
public Object getCredentials() { | |||||
return this.credentials; | |||||
} | |||||
@Override | |||||
public Object getPrincipal() { | |||||
return this.principal; | |||||
} | |||||
@Override | |||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { | |||||
if (isAuthenticated) { | |||||
throw new IllegalArgumentException( | |||||
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); | |||||
} | |||||
super.setAuthenticated(false); | |||||
} | |||||
@Override | |||||
public void eraseCredentials() { | |||||
super.eraseCredentials(); | |||||
} | |||||
} |