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: emp
sa\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; } }