已登录购物车
接下来,我们完成已登录购物车。
在刚才的未登录购物车编写时,我们已经预留好了编写代码的位置,逻辑也基本一致。
添加登录校验
购物车系统只负责登录状态的购物车处理,因此需要添加登录校验,我们通过JWT鉴权即可实现。
引入JWT相关依赖
我们引入之前写的鉴权工具:learn-auth-common
<dependency>
<groupId>com.learn.auth</groupId>
<artifactId>learn-auth-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
配置公钥
learn:
jwt:
pubKeyPath: C:/tmp/rsa/rsa.pub # 公钥地址
cookieName: LY_TOKEN # cookie的名称
加载公钥
代码:
@ConfigurationProperties(prefix = "learn.jwt")
public class JwtProperties {
private String pubKeyPath;// 公钥
private PublicKey publicKey; // 公钥
private String cookieName;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
@PostConstruct
public void init(){
try {
// 获取公钥和私钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
logger.error("初始化公钥失败!", e);
throw new RuntimeException();
}
}
public String getPubKeyPath() {
return pubKeyPath;
}
public void setPubKeyPath(String pubKeyPath) {
this.pubKeyPath = pubKeyPath;
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public String getCookieName() {
return cookieName;
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
}
}
编写拦截器
因为很多接口都需要进行登录,我们直接编写SpringMVC拦截器,进行统一登录校验。同时,我们还要把解析得到的用户信息保存起来,以便后续的接口可以使用。
代码:
public class LoginInterceptor extends HandlerInterceptorAdapter {
private JwtProperties jwtProperties;
// 定义一个线程域,存放登录用户
private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();
public LoginInterceptor(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 查询token
String token = CookieUtils.getCookieValue(request, "LY_TOKEN");
if (StringUtils.isBlank(token)) {
// 未登录,返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
// 有token,查询用户信息
try {
// 解析成功,证明已经登录
UserInfo user = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
// 放入线程域
tl.set(user);
return true;
} catch (Exception e){
// 抛出异常,证明未登录,返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
tl.remove();
}
public static UserInfo getLoginUser() {
return tl.get();
}
}
注意:
-
这里我们使用了
ThreadLocal
来存储查询到的用户信息,线程内共享,因此请求到达Controller
后可以共享User -
并且对外提供了静态的方法:
getLoginUser()
来获取User信息
配置拦截器
配置SpringMVC,使过滤器生效:
@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private JwtProperties jwtProperties;
@Bean
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor(jwtProperties);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
}
}