小白跟着网上各种视频和学习文档一步一步搭建和实现springsecurity-oauth2认证授权项目,老师们都嗖嗖的测试一步就出效果了,自己确始终不得效果。
各种百度,反复观看视频,各种调试配置属性,都一直不行,躺床上左思右想,刚开始时超级抓狂,但也无济于事,慢慢还是得平静下来再重新多来几遍突然就灵光一现通透啦。
问题展示:
java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: com.sherp.security.pojo.SysRole
at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:50) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.deserializeAuthentication(JdbcTokenStore.java:405) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:198) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:196) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:678) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:616) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:699) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:711) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:789) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:195) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:188) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:238) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:83) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:150) [spring-security-oauth2-2.3.5.RELEASE.jar:na]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) [spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) [spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_202]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_202]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_202]
Caused by: java.lang.ClassNotFoundException: com.sherp.security.pojo.SysRole
at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:68) ~[spring-boot-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_202]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_202]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:275) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.core.ConfigurableObjectInputStream.resolveClass(ConfigurableObjectInputStream.java:76) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1868) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) ~[na:1.8.0_202]
at java.util.ArrayList.readObject(ArrayList.java:797) ~[na:1.8.0_202]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_202]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_202]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_202]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_202]
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) ~[na:1.8.0_202]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) ~[na:1.8.0_202]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) ~[na:1.8.0_202]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) ~[na:1.8.0_202]
at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:43) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
... 70 common frames omitted
分析原因:
最开始已为是资源项目中mybaits的pojo别名未设置正确
mybatis:
configuration:
map-underscore-to-camel-case: true #开启驼峰转换模式
type-aliases-package: com.sherp.resource.pojo
还已为是自动覆盖相同名称bean配置未生效
spring:
application:
name: security-resource
main:
allow-bean-definition-overriding: true #自动覆盖相同名称的bean
后发现不论怎么设置问题都一致存在,后实在没办法只能将自定义用户类路径各在资源服务和授权服务调成一致,效果就出来了。但这样却破坏了我的工程包层级,就开始想办法怎么才能不破坏各工程包层级前提还能出效果,于是相处将自定义用户类提取到通用工程中,资源服务和授权服务进行引入,这样调试效果也是对的。但考虑不能将让各项目都对通用工程过于依赖,然后还是回归使用security内置用户对象吧,就是多一步用户对象之间的转换,最终也能达成我所想。
问题原因:
参考网上集成案例自定义的用户类【SysUser 】使用直接实现security内置用户类【UserDetails 】简化用户类之间转换
/**
* @Author: sherp
* @CreateTime: 2022/7/1 21:31
* @Description: 用户类 引用spring security规范
*/
@Data
public class SysUser implements UserDetails {
private Integer id;
private String username;
private String password;
private Integer status;
private List<SysRole> roles = new ArrayList<>();
@JsonIgnore
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles;
}
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
}
解决方案:
方案一:
在资源服务和授权服务工程中将自定义用户类的类路径定义成一致【com.sherp.pojo】;网上案例通常使用此方案,但在各服务工程自己的包层级中不容易一致,顾不推荐使用。
方案二:
将自定义用户类定义在通用工程项目中,各资源服务和授权服务工程引用通用工程进而使用自定义用户类。
方案三:
不直接使用自定义用户类实现security内置的用户类,进而只在授权服务中对自定义用户类对象手动转换成security内置用户对象,而后各资源服务中根据自己需求非必须引入自定义用户类。
/**
* @Author: sherp
* @CreateTime: 2022/7/1 21:31
* @Description: 用户类
*/
@Data
public class SysUser {
private Integer id;
private String username;
private String password;
private Integer status;
private List<SysRole> roles = new ArrayList<>();
}
/**
* @Author: sherp
* @CreateTime: 2022/7/1 21:56
* @Description: 认证用户数据
*/
@Service
@Transactional
public class MyUserServiceImpl implements MyUserService {
@Autowired
UserMapper userMapper;
/*
* 重写方法:根据用户名称获取用户信息
* */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser sysUser = userMapper.findByUserName(username);
//将自定义用户对象转换成security内置用户对象
List<GrantedAuthority> authorities = new ArrayList<>();
List<SysRole> roles = sysUser.getRoles();
for (int i = 0; i < roles.size(); i++) {
authorities.add(new SimpleGrantedAuthority(roles.get(i).getRoleName()));
}
UserDetails userDetails = new User(sysUser.getUsername(),sysUser.getPassword(),authorities);
return userDetails;
}
}
写在最后:第一篇原创文章,为N久以后再遇上此问题有迹可循,为网上共性问题的小伙伴们各种搜索不得答案提供一缕灵光。仅限个人片面思维,谢谢不喜勿喷啦