项目从Khala6升级到Khala7过程,大部分功能可以平滑升级,因为需要升级的代码基本可以使用OpenRewrite提供的能力进行升级。另外升级内容比较多的认证模块,已经封装在khala-authorization-server,使用Khala依赖的项目只需要升级组件版本即可,因此工作量并不大。
一、环境准备
1.1 Java 环境升级
Khala7版本使用了SpringBoot3,SpringBoot3依赖JDK版本最低为JDK17,如原来使用JDK8,需升级到JDK17。
检查当前 Java 版本:
java -version
安装 Java 17:
Windows 安装 JDK 指南:Windows系统部署 JDK
Mac & Linux 安装 JDK 指南:Linux系统部署JDK
二、使用OpenRewrite
OpenRewrite可以帮助项目快速升级代码版本,但只限于通用功能和组件,部分组件和代码仍需手动升级。
2.1 添加OpenRewrite
在项目顶层pom.xml文件中添加以下插件:
<build>
<plugins>
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>6.9.0</version>
<configuration>
<exportDatatables>true</exportDatatables>
<activeRecipes>
<recipe>org.openrewrite.java.migrate.UpgradeToJava17</recipe>
<recipe>org.openrewrite.java.OrderImports</recipe>
<recipe>org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration</recipe>
<recipe>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_4</recipe>
<recipe>org.openrewrite.java.spring.security6.UpgradeSpringSecurity_6_2</recipe>
<recipe>org.openrewrite.java.spring.cloud2024.UpgradeSpringCloud_2024</recipe>
<recipe>org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation</recipe>
<recipe>org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta</recipe>
<recipe>org.openrewrite.java.migrate.jakarta.JavaxServletToJakartaServlet</recipe>
<recipe>org.openrewrite.java.springdoc.SwaggerToSpringDoc</recipe>
<recipe>org.openrewrite.hibernate.validator.HibernateValidator_8_0</recipe>
<recipe>org.openrewrite.java.migrate.jakarta.UpdateApacheShiroDependencies</recipe>
</activeRecipes>
</configuration>
<dependencies>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-migrate-java</artifactId>
<version>3.10.1</version>
</dependency>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-spring</artifactId>
<version>6.8.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2.2 执行升级命令
mvn rewrite:run
等待运行完成后刷新maven,并执行install命令
mvn clean install
三、升级核心依赖
3.1 项目顶层pom父节点升级
<!– 升级前 –>
<parent>
<groupId>com.eshore.khala</groupId>
<artifactId>eshore-khala-jplan-ms</artifactId>
<!– 升级前可能是其他版本,版本不影响,统一升级到khala7 –>
<version>6.3.9</version>
</parent>
<!– 升级后 –>
<parent>
<groupId>com.eshore.khala</groupId>
<artifactId>eshore-khala-jplan-ms</artifactId>
<version>7.3.3</version>
</parent>
四、组件手动升级
因OpenRewrite不支持自动升级一些第三方组件,这些组件需手动升级。如果使用到以下组件,可按照提示手动升级。
4.1 MyBatis Plus版本升级
<!– 升级前 –>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.12</version>
</dependency>
<!– 升级后 –>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.12</version>
</dependency>
4.2 MyBatis Plus Join版本升级
<!– 升级前 –>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
<version>1.4.13</version>
</dependency>
<!– 升级后 –>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId>
<version>1.5.3</version>
</dependency>
4.3 Knife4j版本升级
<!– 升级前 –>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
<!– 升级后 –>
<!– knife4j 原开发者未升级,第三方提供的包:https://github.com/xiaoymin/knife4j/issues/874 –>
<dependency>
<groupId>com.github.xingfudeshi</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.6.0</version>
</dependency>
4.4 spring-security-oauth2版本升级
<!– 升级前 –>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!– 升级后 –>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
</dependency>
升级其他未提及组件。
五、代码手动升级
5.1 Sc-Gateway调整
5.1.1 SCGatewayApp 中排除项作调整
<!– 升级前 –>
@EnableFeignClients
@EnableBaseFeignInterceptor
@EnableDiscoveryClient
@SpringBootApplication(exclude = {WebSecurityAutoConfiguration.class})
public class SCGatewayApp {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SCGatewayApp.class);
application.setWebApplicationType(WebApplicationType.REACTIVE);
application.run(args);
}
}
<!– 升级后 –>
@EnableFeignClients
@EnableBaseFeignInterceptor
@EnableDiscoveryClient
@SpringBootApplication
public class ScGatewayApp {
public static void main(String[] args) {
// nacos新版本导致logback配置冲突,禁用nacos日志配置
System.setProperty("nacos.logging.default.config.enabled", "false");
SpringApplication application = new SpringApplication(ScGatewayApp.class);
application.setWebApplicationType(WebApplicationType.REACTIVE);
application.run(args);
}
}
5.1.2 删除自动配置
删除com.eshore.khala.gateway.autoconfigure.ResourceServerAutoConfiguration文件,该配置已下沉到khala-auth-client-spring-boot-starter组件中。
删除com.eshore.khala.gateway.autoconfigure.CustomErrorWebFluxAutoConfiguration文件,该配置已下沉到khala-common-core组件中。
5.1.3 删除目录或者文件
删除以下目录,下列目录代码功能已下沉到khala-protection-spring-boot-starter组件中。
com.eshore.khala.gateway.filter.context
com.eshore.khala.gateway.filter.encrypt
com.eshore.khala.gateway.filter.escape
com.eshore.khala.gateway.filter.host
com.eshore.khala.gateway.filter.referer
com.eshore.khala.gateway.filter.signature
com.eshore.khala.gateway.filter.sql
com.eshore.khala.gateway.filter.xss
删除以下目录,下列目录代码功能已下沉到khala-openapi-spring-boot-starter组件中。
com.eshore.khala.gateway.filter.openapi
删除以下目录,下列目录代码功能已下沉到khala-auth-client-spring-boot-starter组件中。
com.eshore.khala.gateway.auth
删除以下文件,下列代码功能已下沉到khala-common-core组件中。
com.eshore.khala.gateway.error.JsonErrorWebExceptionHandler
删除以下文件,继承自该文件的类修改为继承自GlobalFilter
com.eshore.khala.gateway.filter.AbstractFilter
5.1.3 修改文件
5.1.3.1 TraceFilter
修改TraceFilter中MDCTraceUtils名称为MdcTraceUtils。(因代码检测到异味修改文件名称)
5.1.3.2 GatewayAutoConfiguration
修改后的代码
@Slf4j
@EnableConfigurationProperties({KhalaGatewayProperties.class})
@Configuration
public class GatewayAutoConfiguration {
@Bean
public ServerCodecConfigurer serverCodecConfigurer() {
return new DefaultServerCodecConfigurer();
}
}
5.1.3.3 GatewaySensitiveWordAutoConfiguration
修改后的代码
@ConditionalOnProperty(
prefix = SensitiveWordProperties.PREFIX,
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
@Configuration
public class GatewaySensitiveWordAutoConfiguration {
@Bean
public SensitiveRequestFilter sensitiveRequestFilter(KhalaGatewayProperties khalaGatewayProperties,
ServerAccessDeniedHandler serverAccessDeniedHandler,
SensitiveWordManager sensitiveWordManager) {
return new SensitiveRequestFilter(khalaGatewayProperties, serverAccessDeniedHandler, sensitiveWordManager);
}
}
5.1.3.4 SensitiveRequestFilter
修改后的代码
@Slf4j
public class SensitiveRequestFilter implements GlobalFilter, Ordered {
private final KhalaGatewayProperties khalaGatewayProperties;
private final ServerAccessDeniedHandler serverAccessDeniedHandler;
private final SensitiveWordManager sensitiveWordManager;
protected static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
public SensitiveRequestFilter(KhalaGatewayProperties khalaGatewayProperties,
ServerAccessDeniedHandler serverAccessDeniedHandler,
SensitiveWordManager sensitiveWordManager) {
this.khalaGatewayProperties = khalaGatewayProperties;
this.serverAccessDeniedHandler = serverAccessDeniedHandler;
this.sensitiveWordManager = sensitiveWordManager;
}
@Override
public int getOrder() {
return GatewayFilterOrder.SENSITIVE_CHECK_ORDER;
}
/**
* @param exchange
* @param chain
* @return get请求参考spring cloud gateway自带过滤器:
* post请求参考spring cloud gateway自带过滤器:
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!khalaGatewayProperties.getSensitive()) {
// 不需要检测敏感词
return chain.filter(exchange);
}
// grab configuration from Config object
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String requestPath = serverHttpRequest.getURI().getPath();
// 访问路径是否需要检查敏感词
if (needNotCheck(khalaGatewayProperties.getSensitiveIgnores(), requestPath)) {
return chain.filter(exchange);
}
RequestContext gatewayContext = exchange.getAttribute(RequestContext.CACHE_GATEWAY_CONTEXT);
if (gatewayContext == null || StringUtils.isBlank(gatewayContext.getRequestBody())) {
return chain.filter(exchange);
}
Set<String> sensitives = sensitiveWordManager.check(URLDecoder.decode(gatewayContext.getRequestBody(), CharsetUtil.CHARSET_UTF_8));
if (CollectionUtils.isNotEmpty(sensitives)) {
StringBuilder message = new StringBuilder();
message.append(MessageSourceUtils.getMessage(GatewayErrorCodeConstants.GATEWAY_CONTAIN_SENSITIVE.getName()));
for (String sensitive : sensitives) {
message.append("【").append(sensitive).append("】");
}
return serverAccessDeniedHandler.handle(exchange, new AccessDeniedException(message.toString()));
}
return chain.filter(exchange);
}
/**
* 当前路径是否需要忽略检查
*
* @param requestPath
* @return
*/
private boolean needNotCheck(Set<String> ignoresUrls, String requestPath) {
return ignoresUrls.stream()
.anyMatch(r -> PATH_MATCHER.match(r, requestPath));
}
}
5.2 UaaServerApp 调整
5.2.1 UaaServerApp中排除项作调整
<!– 升级前 –>
@EnableWebSecurity
@EnableFeignClients
@EnableFeignInterceptor
@EnableDiscoveryClient
@SpringBootApplication(exclude = WebSecurityAutoConfiguration.class)
public class UaaServerApp {
public static void main(String[] args) {
SpringApplication.run(UaaServerApp.class, args);
}
}
<!– 升级后 –>
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableWebSecurity
@EnableFeignClients
@EnableFeignInterceptor
@EnableDiscoveryClient
@SpringBootApplication
public class UaaServerApp {
public static void main(String[] args) {
// nacos新版本导致logback配置冲突,禁用nacos日志配置
System.setProperty("nacos.logging.default.config.enabled", "false");
SpringApplication.run(UaaServerApp.class, args);
}
}
5.2.2 UaaServerApp中扩展代码作调整
Granter 调整
<!– 升级前 –>
package com.eshore.khala.uaa.provider.example;
import com.eshore.khala.authorization.provider.UaaTokenGranter;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.Map;
/**
*
* @author khala
* @date 2023-05-03 16:59
*/
@Service
public class ExampleGranter extends UaaTokenGranter {
/**
* GRANT_TYPE 由/oauth/token接口传入参数
* 传入的参数如果跟此变量相同,则会交给这个granter处理
* 传入的GRANT_TYPE必须要在oauth_client_details表中跟cilent_id相同的对应记录上authorized_grant_types中有分配
*/
private static final String GRANT_TYPE = "example";
public ExampleGranter(AuthenticationManager authenticationManager
, @Lazy DefaultTokenServices tokenServices
, ClientDetailsService clientDetailsService
, OAuth2RequestFactory requestFactory
, AuthenticationEventPublisher authenticationEventPublisher) {
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
super.authenticationManager = authenticationManager;
super.authenticationEventPublisher = authenticationEventPublisher;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
// 获取用户关键参数,可以是username、email、mobile等内容
String example = parameters.get("example");
// 如果有密码则拿密码,没有密码此代码可以删除
String password = parameters.get("password");
parameters.remove("password");
// 这里需要创建此项相关的AuthenticationToken,与ExampleAuthenticationProvider的supports对应
Authentication userAuth = new ExampleAuthenticationToken(example, password);
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
// 调用父类的authenticate,登录成功后推送事件
return super.authenticate(client, tokenRequest, userAuth);
}
}
<!– 升级后 –>
package com.eshore.khala.uaa.provider.example;
import com.eshore.khala.authorization.support.AbstractKhalaAuthenticationConverter;
import com.eshore.khala.authorization.support.AbstractKhalaAuthenticationToken;
import com.eshore.khala.authorization.support.mobilePassword.MobilePasswordAuthenticationToken;
import com.eshore.khala.authorization.utils.OauthEndpointUtils;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import java.util.List;
/**
*
* @author khala
* @date 2023-05-03 16:59
*/
@Service
public class ExampleConverter extends AbstractKhalaAuthenticationConverter {
/**
* 外部传入的自定义参数
*/
private static String PARAM_EXAMPLE = "example";
public ExampleConverter() {
}
@Override
protected String supportGrantType() {
return MobilePasswordAuthenticationToken.GRANT_TYPE.getValue();
}
@Override
protected List<String> paramNames() {
return List.of(PARAM_EXAMPLE, OAuth2ParameterNames.PASSWORD);
}
@Override
protected AbstractKhalaAuthenticationToken getToken(MultiValueMap<String, String> parameters) {
String example = OauthEndpointUtils.getParam(parameters, PARAM_EXAMPLE);
String password = OauthEndpointUtils.getParam(parameters, OAuth2ParameterNames.PASSWORD);
ExampleAuthenticationToken authentication = new ExampleAuthenticationToken(example, password);
authentication.setDetails(parameters);
return authentication;
}
}
Provider作调整
<!– 升级前 –>
package com.eshore.khala.uaa.provider.example;
import com.eshore.khala.authorization.error.UaaErrorCodeConstants;
import com.eshore.khala.authorization.provider.AbstractManagerAuthenticationProvider;
import com.eshore.khala.authorization.service.impl.UserDetailServiceFactory;
import com.eshore.khala.starter.auth.token.KhalaAuthenticationToken;
import com.eshore.khala.starter.i18n.util.MessageSourceUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 扩展用户登录方式示例
* 这里是处理查询用户逻辑,并返回统一KhalaAuthenticationToken给底层使用
* @author khala
* @date 2023-05-03 16:59
*/
@Setter
@Getter
@Service
public class ExampleAuthenticationProvider extends AbstractManagerAuthenticationProvider {
/**
* khala实现的查询用户逻辑
* 与ExampleUserDetailServiceImpl二选一
*/
@Resource
private UserDetailServiceFactory userDetailsServiceFactory;
//
// /**
// * 自定义实现查询用户逻辑
// * 与UserDetailServiceFactory二选一
// */
// @Resource
// private ExampleUserDetailServiceImpl exampleUserDetailService;
@Resource
private PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) {
// granter 传入对应的ExampleAuthenticationToken
ExampleAuthenticationToken authenticationToken = (ExampleAuthenticationToken) authentication;
// 传入的用户关键信息,可以是登录账号,手机号,邮箱等等
String wxOpenId = (String) authenticationToken.getPrincipal();
String password = (String) authenticationToken.getCredentials();
// 根据用户关键信息查询用户
UserDetails user = userDetailsServiceFactory.getService(authenticationToken).loadUserByOpenId(wxOpenId);
// UserDetails user = exampleUserDetailService.loadUserByWechatOpenId(wxOpenId);
if (user == null) {
// 查询不到用户,返回失败
throw new InternalAuthenticationServiceException(MessageSourceUtils.getMessage(UaaErrorCodeConstants.WRONG_USERNAME_OR_PASSWORD.getName()));
}
// 如果需要校验用户信息,在此校验,可以使用自己的校验逻辑,不需要校验的可以删除代码
super.checkPassword(user.getUsername(), user.getPassword(), password);
// 检查用户状态
super.check(user);
// 返回统一对象,至此登录工作基本完成,转给底层处理生成token
KhalaAuthenticationToken authenticationResult = new KhalaAuthenticationToken(user, password, user.getAuthorities());
authenticationResult.setDetails(authenticationToken.getDetails());
return authenticationResult;
}
/**
* 校验当前的Token是否支持处理
* 由granter传入,如果匹配,则由当前provider处理用户登录逻辑
* @param authentication
* @return
*/
@Override
public boolean supports(Class<?> authentication) {
return ExampleAuthenticationToken.class.isAssignableFrom(authentication);
}
}
<!– 升级后 –>
package com.eshore.khala.uaa.provider.example;
import com.eshore.khala.authorization.error.UaaErrorCodeConstants;
import com.eshore.khala.authorization.service.impl.UserDetailServiceFactory;
import com.eshore.khala.authorization.support.AbstractKhalaAuthenticationProvider;
import com.eshore.khala.starter.auth.token.KhalaAuthenticationToken;
import com.eshore.khala.starter.i18n.util.MessageSourceUtils;
import com.eshore.khala.starter.tenant.core.context.TenantContextHolder;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.stereotype.Service;
/**
* 扩展用户登录方式示例
* 这里是处理查询用户逻辑,并返回统一KhalaAuthenticationToken给底层使用
* @author khala
* @date 2023-05-03 16:59
*/
@Setter
@Getter
@Service
public class ExampleAuthenticationProvider extends AbstractKhalaAuthenticationProvider {
/**
* khala实现的查询用户逻辑
* 与ExampleUserDetailServiceImpl二选一
*/
@Resource
private UserDetailServiceFactory userDetailsServiceFactory;
/**
* 查询用户信息,返回给KhalaAuthenticationToken并转底层处理生成token
* @param authentication
* @return
*/
@Override
protected Authentication getPrincipal(Authentication authentication) {
// granter 传入对应的ExampleAuthenticationToken
ExampleAuthenticationToken authenticationToken = (ExampleAuthenticationToken) authentication;
// 传入的用户关键信息,可以是登录账号,手机号,邮箱等等
String example = (String) authenticationToken.getPrincipal();
String password = (String) authenticationToken.getCredentials();
// 根据用户关键信息查询用户,可根据情况修改不同的函数查询用户信息
UserDetails user = userDetailsServiceFactory.getService(authenticationToken).loadUserByOpenId(example);
if (user == null) {
// 查询不到用户,返回失败
throw new InternalAuthenticationServiceException(MessageSourceUtils.getMessage(UaaErrorCodeConstants.WRONG_USERNAME_OR_PASSWORD.getName()));
}
// 如果需要校验用户信息,在此校验,可以使用自己的校验逻辑,不需要校验的可以删除代码
super.checkPassword(user.getUsername(), user.getPassword(), password);
// 检查用户状态
super.check(user);
// 返回统一对象,至此登录工作基本完成,转给底层处理生成token
KhalaAuthenticationToken authenticationResult = new KhalaAuthenticationToken(TenantContextHolder.getTenantIdLong(), user, password, user.getAuthorities());
authenticationResult.setDetails(authenticationToken.getDetails());
return authenticationResult;
}
/**
* 登录类型
* @return
*/
@Override
protected AuthorizationGrantType grantType() {
return ExampleAuthenticationToken.GRANT_TYPE;
}
/**
* 是否需要检查验证码
*
* @return
*/
@Override
protected boolean checkCaptcha() {
return false;
}
/**
* 校验当前的Token是否支持处理
* 由granter传入,如果匹配,则由当前provider处理用户登录逻辑
* @param authentication
* @return
*/
@Override
public boolean supports(Class<?> authentication) {
return ExampleAuthenticationToken.class.isAssignableFrom(authentication);
}
}
AuthenticationToken作调整
<!– 升级前 –>
/**
*
*/
package com.eshore.khala.uaa.provider.example;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import java.util.Collection;
/**
* AuthenticationToken示例
* 可以增加登录需要传输的用户参数
*
* @author khala
* @date 2023-05-03 16:59
*/
public class ExampleAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
// ~ Instance fields
// ================================================================================================
private final Object principal;
private Object credentials;
// ~ Constructors
// ===================================================================================================
/**
* This constructor can be safely used by any code that wishes to create a
* <code>SocialUserAuthenticationToken</code>, as the {@link #isAuthenticated()}
* will return <code>false</code>.
*
*/
public ExampleAuthenticationToken(String mobile, String password) {
super(null);
this.principal = mobile;
this.credentials = password;
super.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 ExampleAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(false);
}
// ~ Methods
// ========================================================================================================
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) {
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();
}
}
<!– 升级后 –>
/**
*
*/
package com.eshore.khala.uaa.provider.example;
import com.eshore.khala.authorization.support.AbstractKhalaAuthenticationToken;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
/**
* AuthenticationToken示例
* 可以增加登录需要传输的用户参数
*
* @author khala
* @date 2023-05-03 16:59
*/
public class ExampleAuthenticationToken extends AbstractKhalaAuthenticationToken {
/**
* GRANT_TYPE 由/oauth/token接口传入参数
* 传入的参数如果跟此变量相同,则会交给这个convert处理
* 传入的GRANT_TYPE必须要在oauth2_registered_client表中跟client_id相同的对应记录上authorization_grant_types中有分配
*/
public static final AuthorizationGrantType GRANT_TYPE = new AuthorizationGrantType("Example");
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object principal;
private Object credentials;
public ExampleAuthenticationToken(String example, String password) {
super(GRANT_TYPE);
this.principal = example;
this.credentials = password;
super.setAuthenticated(false);
}
// ~ Methods
// ========================================================================================================
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) {
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();
}
}
六、其他情况处理
6.1 升级后找不到类文件
6.1.1 可能原因: 升级后将功能移入新的组件包下。
解决方案:打开https://mvnrepository.com/,查找当前组件名称,看当前组件是否有迁移到新的组件中,如有迁移,则使用新的组件;
6.1.2 可能原因: 升级后组件调整了该类的命名空间。
解决方案:删除该文件的import导入,让IDEA自动插入,或者手动导入;
6.1.3 可能原因: 该类已经被删除;
解决方案:寻找其他替代方案;
6.2 升级后找不到方法
6.2.1 可能原因: 升级后该方法已更改名称。
解决方案:修改成改名后的方法名称;
6.2.2 可能原因: 升级后删除了该方法。
解决方案:寻找其他替代方法;
6.3 升级后参数不匹配
6.3.1 可能原因: 升级后该方法的参数发生变化。
解决方案:按照提示修改调用方法的参数;
6.4 程序启动报java.lang.NoClassDefFoundError错误
6.4.1 可能原因: 升级后该类对应的组件未正确升级。
解决方案:查询组件正确的版本,配置合适的组件版本;
6.4.2 可能原因: 升级后该类对应的组件已改名。
解决方案:查询改名后的组件,配置对应的组件;



