Zuul一个网关插件
作用:
- 每个服务都可以被外界单独访问,所以我们就需要把所有的服务端口给隐藏,对外只提供一个统一访问的地址,
- 对内代理每个服务的路由,派发给某些服务
怎么使用Zuul 先导入zuul的依赖:
org.springframework.cloud spring-cloud-starter-netflix-zuul
导入zuul的依赖后
我们在配置文件中进行相关配置
启动类添加注解
- @EnableZuulProxy声明启用zuul代理
- @EnableEurekaClient开启服务注册发现功能。
- 在把USER服务添加到网关里面
- http://localhost:19000/user/chaxun
- 然后我们就可以通过网关的端口来对用户服务进行访问了
ZuulFilter
- 那么我们怎么使用Zuul给我们提供的过滤器呢?
- 写一个子类过滤器来继承ZuulFilter给我们提供的过滤方法和相关配置
package com.example.s83790cloudzuul.filter;
import com.netflix.zuul.*;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class CustomZuulFilter extends ZuulFilter
{
@Override
public String filterType()
{
//过滤器的类型
// 1)pre
//可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程。
//2)route
//在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。
//3)post
//在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。
//4)error
//处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。
return "pre";
}
@Override
public int filterOrder()
{
//此过滤器的优先级,0的优先级是最高,其他逐渐次知
return 0;
}
@Override
public boolean shouldFilter()
{
//是否开启过滤,开启true 关闭 false
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();//获取当此被拦截的请求
String requestURI = String.valueOf(request.getRequestURL());
String http ="http://127.0.0.1:19000/user/lhj";
return !(requestURI.equals(http));
}
@Override
public Object run() throws ZuulException
{
//获取当前应用请求的上下文
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();//获取当此被拦截的请求
String name = request.getParameter("username");//获取请求中获取某个参数
if (name == null || "".equals(name))
{
//阻止请求进入后续处理
requestContext.setSendZuulResponse(false);//过滤该请求不对其进行路由
requestContext.setResponseStatusCode(404);//返回错误码
}
return null;
}
}
JWT
JWT:令牌权限控制
我们为什么要使用JWT?在原来我们的服务中,前端接收到用户的请求就需要跨域回后端,假如我需要登录,那么我们的流程就是
登录界面 —— 发生请求 > 后端controller ——分配业务> service —— 请求Dao数据> ——>dao
Dao从数据库查完数据之后还要原来返回到前端,并且将用户数据保存在当前会话中session中,这样一来要是访问的人少还好说,但是如果你访问的人多了起来服务器是抗不住的几千万个session或者几亿个
所以就有了JWT JWT产生一个token,在你访问其他页面时会检查你的令牌是不是为空,又或者是不是有效,如果为空或无效的话就不让你访问。
这样一来总是判断你的用户是否登录,而且也不用存到session里面浪费服务器资源,
package com.example.s83790authentication.controller;
import com.google.common.collect.Maps;
import io.jsonwebtoken.*;
import java.util.Date;
import java.util.Map;
public class JWTUtils {
static Map map = Maps.newConcurrentMap();//token里面带的数据
static String miYao = "LHJ_HEN_SHUAIZDHSZDHS";//进行数字签名的私钥
//生成令牌的方法
public static String getToken(String username,String password) {
map.put("username", username);//用户名
map.put("password",password);//密码
//生成令牌
return Jwts.builder()
.setId("tokenid")//设置令牌ID
.setSubject("塞杰博")//设置令牌所属于
.setClaims(map)//设置令牌保存的数据
.setExpiration(new Date(System.currentTimeMillis()+10*1000))//令牌过期时间
.setIssuedAt(new Date(System.currentTimeMillis()))//令牌生效时间
.signWith(SignatureAlgorithm.HS256, miYao)//头部信息 第一个参数为加密方式为哈希256,第二个参数是更具密钥加密
.compact();//生成令牌
}
public static boolean get(String a)//解析令牌内容
{
try {
Jws claimsJws =Jwts.parser().setSigningKey(miYao).parseClaimsJws(a);//把令牌解析成>
Claims claims = claimsJws.getBody();
long guoqi = claims.getExpiration().getTime();//得到令牌的过期时间
long dangq = System.currentTimeMillis();//得到当前时间
System.out.println("过期时间:"+guoqi);
System.out.println("当前时间:"+dangq);
if (guoqi-dangq>0)
{
System.out.println("没过期");
return true;
}
}catch (Exception e)
{
System.out.println("过期");
return false;
}
return true;
}
}
zuul过滤器获取token
package com.example.s83790cloudzuul.filter;
import cn.dev33.satoken.stp.StpUtil;
import com.netflix.zuul.*;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
@Component
public class CustomZuulFilter extends ZuulFilter
{
@Autowired
RestTemplate restTemplate;
@Override
public String filterType()
{
//过滤器的类型
// 1)pre
//可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程。
//2)route
//在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。
//3)post
//在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。
//4)error
//处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。
return "pre";
}
@Override
public int filterOrder()
{
//此过滤器的优先级,0的优先级是最高,其他逐渐次知
return 0;
}
@Override
public boolean shouldFilter()
{
//是否开启过滤,开启true 关闭 false
return true;
}
@Override
public Object run() throws ZuulException
{
//获取当前应用请求的上下文
RequestContext requestContext = RequestContext.getCurrentContext();
String token = StpUtil.getTokenValue();
System.out.println("token:"+token);
if (StpUtil.getLoginIdByToken(token)==null)
{
requestContext.setSendZuulResponse(false);// 过滤该请求,不对其进行路由
requestContext.setResponseStatusCode(505);
requestContext.setResponseBody("请先登录后操作......");
}else
{
if (restTemplate.getForObject("http://AUTHSERVICE/tokenTimeout",String.class).equals("过期"))//远程调用用户服务里面的token方法解析这个token是不是过期
{
System.out.println("过期");
requestContext.setSendZuulResponse(false);// 过滤该请求,不对其进行路由
requestContext.setResponseStatusCode(506);// 返回错误码
requestContext.setResponseBody("令牌过期......");// 返回错误内容
}
}
return null;
}
}
zuul调用其他服务解析token的方法
@RequestMapping("/tokenTimeout")
public String getJwt()
{
System.out.println("token:"+StpUtil.getTokenValue());
return StpUtil.getTokenActivityTimeout()==-2L? "过期":"没过期";
}



