一丶传统获取方法
- 在每次controller中接受token,也就是从请求头中获取token,然后调用tokenUtiils进行解析,出相关的用户信息。进行使用
- 可以使用AOP。
- 使用mvc拦截器HandlerInterceptor+方法参数解析器HandlerMethodArgumentResolver
二丶自定义拦截器实现HandlerInterceptor
在实现过程中,主要复写以下方法,前提是自定义一个注解,然后再我们自定义的拦截器中的前置处理方法中,进行注解识别,当有此注解后被拦截,然后从request中获取token,之后处理,将信息进行处理,可以存入线程,或者request域中。
- 自定义注解
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class UserAuthValidator```
- 实现preHandle方法
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse?, handler: Any?): Boolean {
if (handler is HandlerMethod && handler.hasMethodAnnotation(UserAuthValidator::class.java)) {
val token = tokenUtils.getToken(request)
if (StringUtils.isEmpty(token)) {
throw AuthorizationException()
}
setUserInfo(token ?: "")
setToken(handler, token ?: "")
}
return true
}
- 实现postHandle方法
override fun postHandle(
request: HttpServletRequest?,
response: HttpServletResponse?,
handler: Any?,
modelAndView: ModelAndView?
) {
// 不做任何处理
}
- 实现afterCompletion方法
override fun afterCompletion(
request: HttpServletRequest?,
response: HttpServletResponse?,
handler: Any?,
ex: Exception?
) {
// 资源回收
try {
SessionCache.clearResource()
} catch (e: Throwable) {
// 不做任何处理
}
}
- 下方是我设置userInfo和token信息的代码
/**
* 设置token信息
*/
private fun setToken(handler: HandlerMethod, token: String) {
handler.methodParameters.forEach {
if (it.hasParameterAnnotation(Token::class.java)) {
if (StringUtils.isEmpty(token)) {
throw AuthorizationException()
}
SessionCache.saveToken(token)
return
}
}
}
/**
* 设置当前登陆用户信息
*/
private fun setUserInfo(token: String) {
val userInfo = try {
userPlatformService.getUserInfo(token, AuthorizationTypeEnum.STUDENT.authorizationType)
} catch (e: RestClientException) {
throw AuthorizationException()
}
if (userInfo == null || userInfo.id < 1) {
throw AuthorizationException()
}
SessionCache.saveUserInfo(userInfo)
}
三丶自定义方法参数解析器实现HandlerMethodArgumentResolver
在使用的时候,我们首先自定义注解,这样方便之后在需要的地方直接加该注解,这样就可以将参数实例化,比如在Controller中需要相关用户信息,我们可以通过在参数位置加该注解进行实例化
- 自定注解
@MustBeDocumented
@Target(AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
annotation class UserInfo
- 实现该方法,内部复写supportsParameter,只有该方法返回true,才会进行参数解析resolveArgument
override fun supportsParameter(parameter: MethodParameter?): Boolean {
if (parameter == null) {
return false
}
// 过滤出符合条件的参数,这里指的是加了UserInfo注解的参数
if (parameter.hasParameterAnnotation(UserInfo::class.java)) {
return true
}
return false
}
- 参数解析,从各种缓存,或者说标题1所提到的存储位置进行获取
override fun resolveArgument(
parameter: MethodParameter?,
mavContainer: ModelAndViewContainer?,
webRequest: NativeWebRequest,
binderFactory: WebDataBinderFactory?
): Any {
return SessionCache.getUserInfo() ?: throw throw AuthorizationException()
}
在上方所提到的,如果是在springboot项目中直接加@Componet进行注解,如果是springmvc项目,需继承WebMvcConfigurationSupport。分别在addInterceptors和addArgumentResolvers方法中,添加自定义的拦截器和参数解析器