SaToken实现微服务内部接口调用免认证(无web上下文的情况下)

SaToken实现微服务内部接口调用免认证(无web上下文的情况下)

背景

在微服务中使用过SaToken的朋友可能跟我一样遇到了这样的问题。在无web上下文的情况下(定时任务、不与前端交互独立计算服务)调用服务间接口,由于没有token信息,调用接口时难以越过SaToken的权限认证体系。今天,我在xxljob中调用其他服务上面的接口就遇到了这个问题。

思路

本来想着自己在后端生成一个长期的token,供服务间调用使用。后来觉得麻烦,于是在拦截feign请求的拦截器上对请求headers做了处理,传了个“特殊的token”,这个特殊的token可以根据自己的想法去实现。总之这个token伴随请求达到具体的微服务模块时,在SatToken的认证拦截器里面做个判断,如果判断为是,则不需要进行权限认证。

实现

一、改造feign请求拦截器

public class FeignInterceptor implements RequestInterceptor {

    /**
     * 为 Feign 的 RCP调用 添加请求头Same-Token 和token
     *
     * @param requestTemplate
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
    	// SaSameToken 主要用于实现网关统一请求。即请求不能绕过网关去访问某个具体的服务
        requestTemplate.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());
        try {
            // 当存在web上下文的时候,就正常在请求里面塞进去登录的时候申请到的token
            requestTemplate.header(***monConstants.TOKEN_NAME, ***monConstants.TOKEN_PREFIX + StpUtil.getTokenValue());
        } catch (Exception e) {
            //在无web上下文的情况下,上面try里面的获取用户token的方法StpUtil.getTokenValue()会抛出错误,
            //这里将抛出异常视为无web上下文的情况。无web上下文的时候,token的值赋值为SaSameToken的值,
            //这个情况下,token的值可以通过自己的想法去赋值,不一定与我的想法一致。
            requestTemplate.header(***monConstants.TOKEN_NAME, SaSameUtil.getToken());
        }
    }
}

二、重写认证方法

@Configuration(proxyBeanMethods = false)
public class SecurityConfiguration implements WebMv***onfigurer {

    /**
     * 注册sa-token的拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注解拦截器,该拦截器(SaInterceptor)实现了注解式权限的检查。判断用户是否拥有访问接口所申明的权限
        // 该拦截器有官方实现,我们要做的是重写一个拦截器,记得要继承官方的拦截器,
        // 重写他的 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }
}

下面是重写SaInterceptor拦截器的preHandle方法(我自己定义的拦截器跟官方的拦截器名称一致,大家注意啊。要是不一样的话,addInterceptors()方法里面的拦截器名称记得换成你自己定义的名字,不要整半天没生效来骂我啊/)

@***ponent
@Primary
public class SaInterceptor extends ***.dev33.satoken.interceptor.SaInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        try {
			// 如果请求的header里面的SA-SAME-TOKEN 值和Authorization 值一样,就视为是内部接口调用,就直接返回ture
			// 不在进行认证的相关逻辑。为什么相等时就视为是内部接口调用呢?请看上面的第一部分的feign拦截器的写法。
            String saSameId = request.getHeader("SA-SAME-TOKEN");
            String token = request.getHeader("Authorization");
            if(saSameId.equals(token)){
                return true;
            }
			//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断
			//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断
			//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断
			//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断
            if(this.isAnnotation && handler instanceof HandlerMethod) {

                // 获取此请求对应的 Method 处理函数
                Method method = ((HandlerMethod) handler).getMethod();

                // 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权
                if(SaStrategy.me.isAnnotationPresent.apply(method, SaIgnore.class)) {
                    return true;
                }

                // 注解校验
                SaStrategy.me.checkMethodAnnotation.a***ept(method);
            }

            // Auth 校验
            this.auth.run(handler);

        } catch (StopMatchException e) {
            // 停止匹配,进入Controller
        } catch (BackResultException e) {
            // 停止匹配,向前端输出结果
            if(response.getContentType() == null) {
                response.setContentType("text/plain; charset=utf-8");
            }
            response.getWriter().print(e.getMessage());
            return false;
        }

        // 通过验证
        return true;
    }

}

如果该文章帮到了您,请记得点咋,谢谢/

转载请说明出处内容投诉
CSS教程_站长资源网 » SaToken实现微服务内部接口调用免认证(无web上下文的情况下)

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买