0


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

背景

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

思路

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

实现

一、改造feign请求拦截器

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

二、重写认证方法

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

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

@Component@PrimarypublicclassSaInterceptorextendscn.dev33.satoken.interceptor.SaInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{try{// 如果请求的header里面的SA-SAME-TOKEN 值和Authorization 值一样,就视为是内部接口调用,就直接返回ture// 不在进行认证的相关逻辑。为什么相等时就视为是内部接口调用呢?请看上面的第一部分的feign拦截器的写法。String saSameId = request.getHeader("SA-SAME-TOKEN");String token = request.getHeader("Authorization");if(saSameId.equals(token)){returntrue;}//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断//下面的逻辑跟官方一模一样,我只加了上面两行代码和判断if(this.isAnnotation && handler instanceofHandlerMethod){// 获取此请求对应的 Method 处理函数Method method =((HandlerMethod) handler).getMethod();// 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权if(SaStrategy.me.isAnnotationPresent.apply(method,SaIgnore.class)){returntrue;}// 注解校验SaStrategy.me.checkMethodAnnotation.accept(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());returnfalse;}// 通过验证returntrue;}}

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

标签: 微服务 前端 架构

本文转载自: https://blog.csdn.net/qq_36613617/article/details/132459655
版权归原作者 程序员劝退师·咩 所有, 如有侵权,请联系我们删除。

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

还没有评论