【原创】Spring-Cloud架构入门(三)网关与服务鉴权方案--转载请注明出处

一、网关Zuul

SpringCloud的Zuul组件,为我们提供了路由转发的功能,同时在路由过程中,还可以进行日志打印,权限控制等功能。日志打印以及权限控制可以通过实现ZuulFilter来进行:

package com.zhou.config;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class MyFilter extends ZuulFilter {

    /**
     * 返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
     * pre 路由之前
     * routing 路由之时
     * post 路由之后
     * error 发生错误时
     * 常亮可以查看 FilterConstants
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤器的过滤顺序
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 这里可以写逻辑判断,是否要过滤,true,永远过滤。
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(request.getRequestURI());
        System.out.println(request.getRequestURL());
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }
        return null;
    }
}

上面的代码中,就进行了一个最简单的权限校验功能(实际的权限控制比这个复杂的多,下面会详细讲解)。通过Filter,还可以在网关层进行日志打印的功能,但是在日志打印时,需要注意我们进行打印请求头与响应体时,需要从Request和Response中获取IO流来进行打印,而普通IO是无法进行复用的,因此,需要注意在打印日志时,需要将文件下载上传类的接口过滤,以避免文件内容为空的问题。

二、网关层服务鉴权方案

网关层服务鉴权方案属于一种比较常见的服务鉴权方案,在权限需要灵活配置的情况下用此方案比较好,该方案的优势在于不与业务代码耦合,是否开放接口,可以通过后台进行设置,而不需要去变更代码。

权限绑定关系:url -> 前端Model -> 权限包集合 -> 用户角色

下方流程图即为鉴权流程:

在上图中,任何用户访问后台需要经过以下步骤:

1.请求被网关层拦截

2.网关层请求鉴权服务进行鉴权,查看是否具有权限,不具备权限则将其拦截

3.网关层转发至服务层

同时,权限的url变更,只需要由后台人员对鉴权服务中的数据进行变更即可,不需要变更后端的服务代码,同时,后端的服务业务开发人员也不需要关注权限url的变更。

三、Controller层AOP鉴权

Controller层AOP鉴权与网关层鉴权有所不同,其权限绑定结构相比网关层鉴权,减少了一层url层的数据。

权限绑定关系:前端Model -> 权限包集合 -> 用户角色

同时,该方式鉴权优势也具有劣势。

1.劣势

要求被权限保护的接口不能被微服务内部访问,否则会造成重复鉴权。

会导致权限与AOP的注解代码绑死,如果希望取消某个接口的权限,或者新增某个接口的权限,就需要对AOP的注解代码进行变更。

2.优势

可以将参数纳入权限控制。例如:用户A只具有“杭州”的数据的访问权限,那么就需要将请求参数纳入到鉴权的范围中,但是接口的参数模型是不一样的,此时利用AOP注解就可以进行轻松的鉴权配置,而网关层不行。

可以减少配置的权限数量,并且去掉url层的权限数据,直接在AOP注解上配置前端Model层的权限信息。

四、总结

目前,在我周围使用SpringCloud的公司中,分采用网关层鉴权的方案进行鉴权的较多,但是两种方案本身是各有优劣的,并没有实际的孰好孰坏。

其实本质上,权限的校验方案本身都比较通用化,但是因为权限本身,需要对大量的接口进行拦截处理,并且,每次鉴定权限在无缓存支撑的情况下,会每一次查询多张数据库表,吃掉大量的服务器性能。因此,在进行鉴权系统的开发时,无论采用哪一种方案,做好适当的多级缓存,才是重中之重。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章