您的位置:首页 > 其它

乐优商城:笔记(十三):鉴权微服务——鉴权

2019-06-06 21:06 330 查看
版权声明:转载请说明 https://blog.csdn.net/sinat_38570489/article/details/91045823

文章目录

      接上一篇鉴权微服务——授权,我们只完成了登录授权功能,鉴权功能还没实现,有很多的微服务必须登陆了才能访问,未登录状态下是无法访问的,与其在各个微服务中编写校验逻辑,还不如在网关Zuul中编写,反正所有请求都会经过Zuul,如果Zuul不放行,那么压根都不会达到微服务。接下来我们在Zuul中完成登录校验拦截

1 配置公钥

既然要鉴权,那就需要公钥:

ly:
jwt:
pubKeyPath: H:/javacode/idea/rsa/rsa.pub # 公钥地址
cookieName: LY_TOKEN

2 引入依赖

<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>ly-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.service</groupId>
<artifactId>ly-auth-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>

3 编写属性类

编写属性类,读取公钥

@Data
@ConfigurationProperties(prefix = "ly.jwt")
public class JwtProperties {

private String pubKeyPath;// 公钥
private String cookieName;

private PublicKey publicKey; // 公钥

// 对象一旦实例化后,就应该读取公钥和私钥
@PostConstruct // 构造函数执行完毕后就执行
public void init(){
// 获取公钥和私钥
try {
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}

4 编写过滤器逻辑

基本逻辑:

  • 获取cookie中的token
  • 通过JWT对token进行校验
  • 通过:则放行;不通过:则重定向到登录页

@Component
@EnableConfigurationProperties({JwtProperties.class, FilterProperties.class})
public class AuthFilter extends ZuulFilter{

@Autowired
private JwtProperties prop;
@Autowired
private FilterProperties filterProperties;

//前置过滤器
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
//官方前置过滤器-1,可以把自己定义的过滤器放在官方过滤器之前
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
// 是否过滤
@Override
public boolean shouldFilter() {
return true
}

@Override
public Object run() throws ZuulException {
// 获取上下文
RequestContext ctx = RequestContext.getCurrentContext();
// 获取request
HttpServletRequest request = ctx.getRequest();
// 获取token
String token = CookieUtils.getCookieValue(request, prop.getCookieName());

// 解析token
try {
UserInfo user = JwtUtils.getInfoFromToken(token, prop.getPublicKey());
} catch (Exception e) {
// 解析失败 未登录
ctx.setSendZuulResponse(false);// 拦截功能
ctx.setResponseStatusCode(403);// 返回状态码
}
return null;
}
}

刷新页面,发现请求校验的接口、甚至登陆的请求也被拦截了:

5 白名单

要注意,并不是所有的路径我们都需要拦截,例如:

  • 登录校验接口:
    /auth/**
  • 注册接口:
    /user/register
  • 数据校验接口:
    /user/check/**
  • 发送验证码接口:
    /user/code
  • 搜索接口:
    /search/**

另外,跟后台管理相关的接口,因为我们没有做登录和权限,因此暂时都放行,但是生产环境中要做登录校验。比如商品微服务,商品微服务中有很多跟查询相关的接口,因此要放行:

  • 后台商品服务:
    /item/**

所以,我们需要在拦截时,配置一个白名单,如果在名单内,则不进行拦截。

application.yaml
中添加规则:


然后编写一个类注入这些属性:

@Data
@ConfigurationProperties(prefix = "ly.filter")
public class FilterProperties {
private List<String> allowPaths;
}

我们接下来修改拦截器,重写

shouldFilter()
方法:

@Override
public boolean shouldFilter() {

// 获取上下文以及request
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();

// 获取请求的URL路径
String path = request.getRequestURI();

// 判断是否在白名单内 如果在 则放行
return !isAllowPath(path);//是否过滤
}

private boolean isAllowPath(String path) {
List<String> allowPaths = filterProperties.getAllowPaths();
for (String allowPath : allowPaths) {
if(path.startsWith(allowPath)){
return true;
}
}
return false;
}

再次测试:

ok!

6 可优化的点

权限系统还需要完善的点:

  • 需要引入权限控制系统 引入权限控制系统一般数据库还需要几张表:权限表、用户表等,几张表中产生一定的关联,一般是多对多关系,用户有了角色就有了权限,权限决定这个用户可以访问哪些路径
  • 在AuthFilter中,应该判断权限
  • 授权中心还可以做服务间的鉴权
  • 7 常见问题——微服务的安全问题

    • 如果cookie被禁用怎么办? 首先提示用户cookie不可以被禁用
    • 把cookie放入头中返回,JS获取头信息,存入web存储(localstorage,SessionStorage),每次请求都需要手动携带token,写入头中
  • 如果cookie被盗用怎么办?
      我们的cookie无法被篡改
    • 加入ip地址识别身份到payload中(不太好)
    • 使用HTTPS协议,防止数据泄露
  • 如果微服务地址被暴露怎么办?
      首先地址不会被暴露,因为所有的微服务都通过Zuul进行访问,对外暴露的只有Zuul
    • 万一暴露了,我们可以加入服务间鉴权 后台需要一个专门的权限管理页面,用来管理微服务以及微服务之间的访问权限,这就需要额外几张表,定义所有微服务的身份信息比如ID等等,再来一张表就是微服务的权限表,记录其中一个微服务可访问的其他微服务,以此类推,形成一个表关联;这样,一个微服务要想访问另外一个微服务,必须在授权页面进行授权才可以,同时这些权限关系都被写入数据库;这样一个微服务要访问另外一个微服务要先去Auth微服务携带着自己的ID和密码发起请求获得权限,之后Auth拿着信息去数据库中查询,如果正确就去读取权限表,如果通过,则生成token返回,之后每次访问都携带这个token,当请求达到微服务,微服务解析token,如果有效,则放行,否则拒绝访问
    • 难点:微服务A启动后自动的向Auth鉴权中心发起认证请求,可以设置在项目启动时便去认证,然后缓存token,之后拦截服务间调用的每一次请求(目前微服务之间通过Feign实现同步调用)判断有没有token,没有的话要去申请,有的话携带token一起发送到另一个微服务B当中,微服务B也要写一个拦截器,先判断token,有权限就放行
  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: