各个微服务的访问需要网关统一管理进行跳转,而在访问网关时,我们可以进行增强功能,通过过虑器实现请求过虑,身份校验
等。
/**
* 身份校验过滤器
*/
@Component
public class LoginFilter extends ZuulFilter {
@Autowired
AuthService authService;
/**
* 过滤器类型 4种
* pre:请求在被路由之前
* 执行routing:在路由请求时调用
* post:在routing和errror过滤器之后调用
* error:处理请求时发生错误调用
* @return
*/
@Override
public String filterType() {
//return null 会导致 FilterProcessor - null异常
return "pre";
}
/**
* 过滤器序号
* 越小越优先被执行
* @return
*/
@Override
public int filterOrder() {
return 0;
}
//是否执行过滤器
@Override
public boolean shouldFilter() {
//返回true表示执行此过滤器
return true;
}
//过滤器得内容
//过虑所有请求,判断头部信息是否有Authorization,如果没有则拒绝访问,否则转发到微服务。
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
//得到request
HttpServletRequest request = requestContext.getRequest();
HttpServletResponse response = requestContext.getResponse();
//cookie
String tokenFormCookie = authService.getTokenFormCookie();
if(StringUtils.isEmpty(tokenFormCookie)){
access_denied();
return null;
}
//hear
String tokenFormHeader = authService.getTokenFormHeader(request);
if(StringUtils.isEmpty(tokenFormHeader)){
access_denied();
return null;
}
//redis
long expireFormRedis = authService.getExpireFormRedis(tokenFormCookie);
if(expireFormRedis<0){
access_denied();
return null;
}
return null;
}
//拒绝访问
private void access_denied(){
RequestContext requestContext = RequestContext.getCurrentContext();
//得到request
HttpServletRequest request = requestContext.getRequest();
HttpServletResponse response = requestContext.getResponse();
//拒绝访问
requestContext.setSendZuulResponse(false);
//回复响应
requestContext.setResponseStatusCode(200);
ResponseResult responseResult = new ResponseResult(CommonCode.UNAUTHENTICATED);
String s = JSON.toJSONString(responseResult);
requestContext.setResponseBody(s);
response.setContentType("application/json;charset=utf-8");
}
}
@service
@Service
public class AuthService {
@Autowired
StringRedisTemplate stringRedisTemplate;
//从cookie中获取jwt令牌
public String getTokenFormCookie() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Map<String, String> map = CookieUtil.readCookie(request, "uid");
if(map!=null&&map.get("uid")!=null){
return map.get("uid");
}
return null;
}
//从请求头中获取jwt令牌
public String getTokenFormHeader(HttpServletRequest request) {
String authorization = request.getHeader("Authorization");
if(StringUtils.isEmpty(authorization)){
return null;
}
if(!authorization.startsWith("Bearer ")){
return null;
}
String jwt = authorization.substring(7);
return jwt;
}
//从redis获取过期时间
public long getExpireFormRedis(String access_token){
String key ="user_token:" + access_token;
Long expire = stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
return expire;
}
}
可以从代码中看到,我们LoginFilter继承ZuulFilter后实现4个子方法,分别是1.过滤器的类型(处理时机), 2.此过滤器的优先级 3.是否执行此过滤器 4.过滤器的内容。
我们实现了一个在请求被路由之前的身份验证功能,在4中获取request中的
1.判断request中的cookie是否有jwt身份短令牌,没有则拒绝访问
2.判断request的Header中是否有jwt令牌,没有则拒绝访问
3.判断redis中此令牌是否过期,过期则拒绝访问
最后,都满足则路由跳转至指定微服务,不满足则response返回未登录授权异常