文章目录  1、单点登录解决方案   2、user服务-登录接口 2.1、UserController 2.2、UserInfoServiceImpl 2.3、载荷 2.4、响应 2.5、Redis Desktop Manager 3、user服务-登录成功获取用户信息回显 3.1、UserController 3.2、UserInfoServiceImpl 3.3、响应 4、登录状态验证&状态透传分析 4.1、gateway-过滤器统一校验登录状态   4.2、登录状态透传拦截器 4.2.1、SpzxServiceAuthInterceptor 4.2.2、H5SpzxWebMvcConfigurer 4.2.3、@EnableSpzxServiceAuth 4.2.4、UserInfoServiceImpl 5、登录校验状态透传总结   
 
 
 
	@Operation (  summary =  "用户登录接口" ) @PostMapping ( "/login" ) public  Result  login ( @RequestBody  UserInfo  userInfo)  { String  token =  userInfoService. login ( userInfo) ; return  Result . ok ( token) ; } 
    @Override public  String  login ( UserInfo  userInfo)  { String  username =  userInfo. getUsername ( ) ; String  password =  userInfo. getPassword ( ) ; if  ( StringUtils . isEmpty ( username)  ||  StringUtils . isEmpty ( password) )  { throw  new  SpzxException ( ResultCodeEnum . LOGIN_PARAMS_ERROR ,  null ) ; } UserInfo  dbUserInfo =  this . getOne ( Wrappers . lambdaQuery ( UserInfo . class ) . eq ( UserInfo :: getUsername ,  username) ) ; if  ( dbUserInfo ==  null )  { throw  new  SpzxException ( ResultCodeEnum . LOGIN_USERNAME_ERROR ,  null ) ; } if  ( dbUserInfo. getStatus ( )  !=  1 )  { throw  new  SpzxException ( ResultCodeEnum . LOGIN_USER_STATUS_ERROR ,  null ) ; } String  encodePwd =  DigestUtils . md5DigestAsHex ( ( DigestUtils . md5DigestAsHex ( password. getBytes ( ) )  +  dbUserInfo. getSalt ( ) ) . getBytes ( ) ) ; if  ( ! encodePwd. equals ( dbUserInfo. getPassword ( ) ) )  { throw  new  SpzxException ( ResultCodeEnum . LOGIN_PASSWORD_ERROR ,  null ) ; } String  token =  IdUtil . getSnowflake ( 1 ,  1 ) . nextIdStr ( ) ; dbUserInfo. setPassword ( null ) ; dbUserInfo. setSalt ( null ) ; redisTemplate. opsForValue ( ) . set ( "spzx:user:login:"  +  token,  dbUserInfo,  7 ,  TimeUnit . DAYS ) ; ServletRequestAttributes  requestAttributes =  ( ServletRequestAttributes )  RequestContextHolder . getRequestAttributes ( ) ; HttpServletRequest  request =  requestAttributes. getRequest ( ) ; return  token; } 
{ "username" :  "18947628476" , "password" :  "123456" 
} 
{ "code" : 200 , "message" : "SUCCESS" , "data" : "1801188891328385024" } 
 
{ "@class" :  "com.atguigu.spzx.model.entity.h5.UserInfo" , "id" :  1774759294596579329 , "createTime" :  [ "java.util.Date" , "2024-04-01 19:22:44" ] , "updateTime" :  [ "java.util.Date" , 1718243055000 ] , "deleted" :  false , "username" :  "18947628476" , "password" :  null , "nickName" :  "小弟" , "avatar" :  "https://cdn.apifox.com/app/project-icon/builtin/16.jpg" , "sex" :  null , "phone" :  null , "memo" :  null , "openId" :  null , "unionId" :  null , "lastLoginIp" :  null , "lastLoginTime" :  null , "status" :  1 , "salt" :  null 
} 
 
    @Operation (  summary =  "查询用户信息回显接口" ) @GetMapping ( "/auth/getCurrentUserInfo" ) public  Result  getCurrentUserInfo ( @RequestHeader ( value =  "token" , required =  false ) String  token)  { UserInfoVo  userInfoVo =  userInfoService. getCurrentUserInfo ( token) ; return  Result . ok ( userInfoVo) ; } 
    @Override public  UserInfoVo  getCurrentUserInfo ( String  token)  { UserInfo  userInfo =  ( UserInfo )  redisTemplate. opsForValue ( ) . get ( "spzx:user:login:"  +  token) ; if  ( userInfo ==  null )  { throw  new  SpzxException ( ResultCodeEnum . LOGIN_STATUS_ERROR ,  null ) ; } UserInfoVo  userInfoVo =  new  UserInfoVo ( ) ; userInfoVo. setNickName ( userInfo. getNickName ( ) ) ; userInfoVo. setAvatar ( userInfo. getAvatar ( ) ) ; return  userInfoVo; } 
{ "code" :  200 , "message" :  "SUCCESS" , "data" :  { "nickName" :  "小弟" , "avatar" :  "https://cdn.apifox.com/app/project-icon/builtin/16.jpg" } 
} 
 
package  com. atguigu. spzx. gateway. filter ; 
import  com. alibaba. nacos. shaded. com. google. gson.  JsonObject ; 
import  com. atguigu. spzx. model. result.  ResultCodeEnum ; 
import  jakarta. annotation.  Resource ; 
import  org. springframework. cloud. gateway. filter.  GatewayFilterChain ; 
import  org. springframework. cloud. gateway. filter.  GlobalFilter ; 
import  org. springframework. core.  Ordered ; 
import  org. springframework. core. io. buffer.  DataBuffer ; 
import  org. springframework. data. redis. core.  RedisTemplate ; 
import  org. springframework. http.  HttpStatus ; 
import  org. springframework. http.  MediaType ; 
import  org. springframework. http. server. reactive.  ServerHttpRequest ; 
import  org. springframework. http. server. reactive.  ServerHttpResponse ; 
import  org. springframework. stereotype.  Component ; 
import  org. springframework. util.  AntPathMatcher ; 
import  org. springframework. util.  StringUtils ; 
import  org. springframework. web. server.  ServerWebExchange ; 
import  reactor. core. publisher.  Mono ; 
@Component 
public  class  GlobalAuthFilter  implements  GlobalFilter ,  Ordered  { @Resource private  RedisTemplate  redisTemplate; @Override public  Mono < Void > filter ( ServerWebExchange  exchange,  GatewayFilterChain  chain)  { ServerHttpRequest  request =  exchange. getRequest ( ) ; String  path =  request. getURI ( ) . getPath ( ) ; AntPathMatcher  matcher =  new  AntPathMatcher ( ) ; if  ( ! matcher. match ( "/**/auth/**" ,  path) )  { return  chain. filter ( exchange) ; } String  token =  request. getHeaders ( ) . getFirst ( "token" ) ; if  ( StringUtils . isEmpty ( token)  ||  ! redisTemplate. hasKey ( "spzx:user:login:"  +  token) )  { ServerHttpResponse  response =  exchange. getResponse ( ) ; response. setStatusCode ( HttpStatus . OK ) ; response. getHeaders ( ) . add ( "Content-Type" ,  MediaType . APPLICATION_JSON_UTF8_VALUE ) ; JsonObject  jsonObject =  new  JsonObject ( ) ; jsonObject. addProperty ( "code" ,  ResultCodeEnum . LOGIN_STATUS_ERROR . getCode ( ) ) ; jsonObject. addProperty ( "message" ,  ResultCodeEnum . LOGIN_STATUS_ERROR . getMessage ( ) ) ; String  json =  jsonObject. toString ( ) ; DataBuffer  buffer =  response. bufferFactory ( ) . wrap ( json. getBytes ( ) ) ; return  response. writeWith ( Mono . just ( buffer) ) ; } return  chain. filter ( exchange) ; } @Override public  int  getOrder ( )  { return  - 1 ; } 
} package  com. atguigu. spzx. common. handler. interceptor ; 
import  com. atguigu. spzx. model. entity. h5.  UserInfo ; 
import  jakarta. annotation.  Resource ; 
import  org. springframework. data. redis. core.  RedisTemplate ; 
import  org. springframework. stereotype.  Component ; 
import  org. springframework. web. servlet.  HandlerInterceptor ; 
@Component 
public  class  SpzxServiceAuthInterceptor  implements  HandlerInterceptor  { @Resource private  RedisTemplate  redisTemplate; public  static  ThreadLocal < UserInfo > THREAD_LOCAL  =  new  ThreadLocal ( ) ; @Override public  boolean  preHandle ( jakarta. servlet. http.  HttpServletRequest,  jakarta. servlet. http.  HttpServletResponse,  Object  handler)  throws  Exception  { String  token =  request. getHeader ( "token" ) ; UserInfo  userInfo =  ( UserInfo )  redisTemplate. opsForValue ( ) . get ( "spzx:user:login:"  +  token) ; THREAD_LOCAL . set ( userInfo) ; return  true ; } @Override public  void  afterCompletion ( jakarta. servlet. http.  HttpServletRequest,  jakarta. servlet. http.  HttpServletResponse,  Object  handler,  Exception  ex)  throws  Exception  { THREAD_LOCAL . remove ( ) ; } 
} package  com. atguigu. spzx. common. handler. interceptor ; 
import  jakarta. annotation.  Resource ; 
import  org. springframework. context. annotation.  Configuration ; 
import  org. springframework. web. servlet. config. annotation.  InterceptorRegistry ; 
import  org. springframework. web. servlet. config. annotation.  WebMvcConfigurer ; 
@Configuration 
public  class  H5SpzxWebMvcConfigurer  implements  WebMvcConfigurer  { @Resource private  SpzxServiceAuthInterceptor  spzxServiceAuthInterceptor; @Override public  void  addInterceptors ( InterceptorRegistry  registry)  { registry. addInterceptor ( spzxServiceAuthInterceptor) . addPathPatterns ( "/**/auth/**" ) ; } 
} package  com. atguigu. spzx. common. handler. interceptor ; 
import  org. springframework. context. annotation.  Import ; 
import  java. lang. annotation.  * ; 
@Target ( ElementType . TYPE ) 
@Retention ( RetentionPolicy . RUNTIME ) 
@Documented 
@Import ( value =  { SpzxServiceAuthInterceptor . class ,  H5SpzxWebMvcConfigurer . class } ) 
public  @interface  EnableSpzxServiceAuth  { 
}     @Override public  UserInfoVo  getCurrentUserInfo ( String  token)  { UserInfo  userInfo =  SpzxServiceAuthInterceptor . THREAD_LOCAL . get ( ) ; UserInfoVo  userInfoVo =  new  UserInfoVo ( ) ; userInfoVo. setNickName ( userInfo. getNickName ( ) ) ; userInfoVo. setAvatar ( userInfo. getAvatar ( ) ) ; return  userInfoVo; }