环境:Spring security oauth2+MmongoDB
描述:refresh token 时报错,请求uri为:
POST http://localhost:8090/api/sso/oauth/token?client_id=clientId&client_secret=clientSecret&grant_type=refresh_token&refresh_token=cdf6ea33-4b5c-472c-b27b-3edfe2192421,
错误信息为:
2021-09-16 17:47:49.688 WARN 800 --- [nio-8090-exec-3] o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: NullPointerException, Cannot invoke "org.springframework.data.mongodb.core.MongoTemplate.findOne(org.springframework.data.mongodb.core.query.Query, java.lang.Class)" because "this.mongoTemplate" is null
2021-09-16 17:47:49.688 INFO 800 --- [nio-8090-exec-3] TheCusWebResponseExceptionTranslator : java.lang.NullPointerException: Cannot invoke "org.springframework.data.mongodb.core.MongoTemplate.findOne(org.springframework.data.mongodb.core.query.Query, java.lang.Class)" because "this.mongoTemplate" is null
2021-09-16 17:47:49.688 WARN 800 --- [nio-8090-exec-3] TheCusWebResponseExceptionTranslator : 空指针异常,错误信息如下:
java.lang.NullPointerException: Cannot invoke "org.springframework.data.mongodb.core.MongoTemplate.findOne(org.springframework.data.mongodb.core.query.Query, java.lang.Class)" because "this.mongoTemplate" is null
2021-09-16 17:47:49.692 WARN 800 --- [nio-8090-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [java.lang.NullPointerException: Cannot invoke "org.springframework.data.mongodb.core.MongoTemplate.findOne(org.springframework.data.mongodb.core.query.Query, java.lang.Class)" because "this.mongoTemplate" is null]
请求token和携带token访问接口都没问题,但刷新token就报错,主要原因是刷新token时经过多次校验。
1,先校验客户端密码(clientsecret)和客户端ID(clientId)。
2,校验refresh token是否合法。
3,根据用户信息生成新token信息。获取用户信息时,即报MongoTemplate错误。具体查看一下,发现是根据用户查询用户信息时,报mongoTemplate is null 错误,既然找到问题所在,下一步就是解决问题。
解决问题:经查阅资料,整理出解决方案。
1,新建MongoDb配置类,配置类如下。
@Configuration
public class MongoDBConfig extends MongoAutoConfiguration {
@Value("${spring.data.mongodb.uri}")
private String connMongoUri;
@Bean
public MongoDatabaseFactory mongoDatabaseFactory(){
MongoDatabaseFactory mongoDatabaseFactory = new SimpleMongoClientDatabaseFactory(connMongoUri);
return mongoDatabaseFactory;
}
@Bean("mongoTemplate")
public MongoTemplate mongoTemplate(){
MongoTemplate mongoTemplate = new MongoTemplate(mongoDatabaseFactory());
return mongoTemplate;
}
}
2,配置上下文类。
@Configuration
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
public static Object getBean(String nameBean){
return getApplicationContext().getBean(nameBean);
}
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String nameBean,Class<T> clazz){
return getApplicationContext().getBean(nameBean,clazz);
}
}
3,从上下文中引用。
@Service
public class SysUserService extends BaseService<SysUserEntity> implements UserDetailsService {
@Autowired
private MongoTemplate mongoTemplate;
public SysUserService(){ super(SysUserEntity.class);}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.info("用户名为:"+username);
Criteria criteria = Criteria.where("username").is(username);
if(mongoTemplate==null){
logger.warn("mongoTemplate is null");
mongoTemplate = SpringContext.getBean("mongoTemplate",MongoTemplate.class);
}
SysUserEntity sysUser = mongoTemplate.findOne(Query.query(criteria),SysUserEntity.class);
if(sysUser == null){
// logger.warn("—---loadUserByUsername---------:用户不存在");
CustomException.generateError(ResultCodeEnum.Fail_用户不存在);
}
return sysUser;
}
}
至此,问题得以完美解决。
提示:也可以不用上下文类(SpringContext),使用静态方法的方式调用,但参数connMongoUri必须写为静态,更改之时多有不便,故舍弃此种方法。