046 用户登录功能02----前端代码和网关的登录拦截器
1.
这里需要向后台发起请求,根据cookie获取当前用户的信息。
(1)
打开js,发现里面已经定义好了Vue组件,并且在created函数中,查询用户信息:
查看网络控制台,发现发起了请求:
因为token在cookie中,因此本次请求肯定会携带token信息在头中。
(2)
-
请求方式:GET
-
请求路径:/verify
-
请求参数:无,不过我们需要从cookie中获取token信息
-
返回结果:UserInfo,校验成功返回用户信息;校验失败,则返回401
/** * 验证用户信息 * @param token * @return */ @GetMapping("verify") public ResponseEntity<UserInfo> verifyUser(@CookieValue("LY_TOKEN")String token){ try { // 从token中解析token信息 UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.prop.getPublicKey()); // 解析成功返回用户信息 return ResponseEntity.ok(userInfo); } catch (Exception e) { e.printStackTrace(); } // 出现异常则,响应500 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); }
(3)测试
重启leyou-auth-service微服务
(4)
那么问题来了:我们怎么知道用户有操作呢?
/** * 验证用户信息 * @param token * @return */ @GetMapping("verify") public ResponseEntity<UserInfo> verifyUser(@CookieValue("LY_TOKEN")String token, HttpServletRequest request, HttpServletResponse response){ try { // 从token中解析token信息 UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.properties.getPublicKey()); // 解析成功要重新刷新token token = JwtUtils.generateToken(userInfo, this.properties.getPrivateKey(), this.properties.getExpire()); // 更新cookie中的token CookieUtils.setCookie(request, response, this.properties.getCookieName(), token, this.properties.getCookieMaxAge()); // 解析成功返回用户信息 return ResponseEntity.ok(userInfo); } catch (Exception e) { e.printStackTrace(); } // 出现异常则,响应500 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); }
2.
<dependency> <groupId>lucky.leyou.auth</groupId> <artifactId>leyou-auth-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>lucky.leyou.common</groupId> <artifactId>leyou-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
然后编写application.yml属性文件,添加如下内容:
leyou:
jwt:
pubKeyPath: D:\temp\rsa\\rsa.pub # 公钥地址
cookieName: LY_TOKEN #cookie的名称
编写属性类,读取公钥:
package lucky.leyou.config; import lucky.leyou.auth.utils.RsaUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.properties.ConfigurationProperties; import javax.annotation.PostConstruct; import java.security.PublicKey; @ConfigurationProperties(prefix = "leyou.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; } }
(2)
-
获取cookie中的token
-
通过JWT对token进行校验
-
package lucky.leyou.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import lucky.leyou.auth.utils.JwtUtils; import lucky.leyou.common.utils.CookieUtils; import lucky.leyou.config.JwtProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component @EnableConfigurationProperties(JwtProperties.class) public class LoginFilter extends ZuulFilter { @Autowired private JwtProperties properties; @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 5; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { // 获取上下文 RequestContext context = RequestContext.getCurrentContext(); // 获取request HttpServletRequest request = context.getRequest(); // 获取token String token = CookieUtils.getCookieValue(request, this.properties.getCookieName()); // 校验 try { // 校验通过什么都不做,即放行 JwtUtils.getInfoFromToken(token, this.properties.getPublicKey()); } catch (Exception e) { // 校验出现异常,返回403 context.setSendZuulResponse(false); context.setResponseStatusCode(HttpStatus.FORBIDDEN.value()); } return null; } }
重启,刷新页面,发现请求校验的接口也被拦截了:
证明我们的拦截器生效了,但是,这个路径似乎不应该被拦截啊!
(3)
-
登录校验接口:
/auth/**
-
注册接口:
/user/register
-
数据校验接口:
/user/check/**
-
发送验证码接口:
/user/code
-
搜索接口:
/search/**
另外,跟后台管理相关的接口,因为我们没有做登录和权限,因此暂时都放行,但是生产环境中要做登录校验:
-
后台商品服务:
/item/**
所以,我们需要在拦截时,配置一个白名单,如果在名单内,则不进行拦截。
在application.yaml
leyou: filter: allowPaths: - /api/auth - /api/search - /api/user/register - /api/user/check - /api/user/code - /api/item
package lucky.leyou.config; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; @ConfigurationProperties(prefix = "leyou.filter") public class FilterProperties { private List<String> allowPaths; public List<String> getAllowPaths() { return allowPaths; } public void setAllowPaths(List<String> allowPaths) { this.allowPaths = allowPaths; } }
package lucky.leyou.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import lucky.leyou.auth.utils.JwtUtils; import lucky.leyou.common.utils.CookieUtils; import lucky.leyou.config.FilterProperties; import lucky.leyou.config.JwtProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * 拦截过滤器 */ @Component @EnableConfigurationProperties({JwtProperties.class, FilterProperties.class}) public class LoginFilter extends ZuulFilter { @Autowired private JwtProperties properties; @Autowired private FilterProperties filterProp; @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 5; } @Override public Object run() throws ZuulException { // 获取上下文 RequestContext context = RequestContext.getCurrentContext(); // 获取request HttpServletRequest request = context.getRequest(); // 获取token String token = CookieUtils.getCookieValue(request, this.properties.getCookieName()); // 校验 try { // 校验通过什么都不做,即放行 JwtUtils.getInfoFromToken(token, this.properties.getPublicKey()); } catch (Exception e) { // 校验出现异常,返回403 context.setSendZuulResponse(false); context.setResponseStatusCode(HttpStatus.FORBIDDEN.value()); } return null; } @Override public boolean shouldFilter() { // 获取上下文 RequestContext ctx = RequestContext.getCurrentContext(); // 获取request HttpServletRequest req = ctx.getRequest(); // 获取路径 String requestURI = req.getRequestURI(); // 判断白名单 // 遍历允许访问的路径 for (String path : this.filterProp.getAllowPaths()) { // 然后判断是否是符合 if(requestURI.startsWith(path)){ return false; } } return true; } }
分类:
乐优商城项目
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)