栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring cloud alibaba 集成feign 自定义feign权限注解 某接口只允许feign访问 附带所有流程以及代码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring cloud alibaba 集成feign 自定义feign权限注解 某接口只允许feign访问 附带所有流程以及代码

本文是《从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(三) (mini-cloud) 搭建认证服务(认证/资源分离版) oauth2.0 (上)》篇的feign 集成篇

主要流程介绍
##1.本文 fegin使用场景
##2.集成fegin 以及目录结构
##3.自定义扫面注解注入fegin service
##4.设置fegin 传递token header
##5.设计某接口只允许feign访问实现原理
##6.开发只允许fegin注解以及拦截器源码
1.本文 fegin使用场景

本文主要介绍使用场景:

1.是在我们的mini-cloud框架中实现授权时feign回调我们upms服务获取用户信息

具体upms数据获取可以参考上篇《spring boot /spring cloud 集成fluent-mybatis + druid 及案例代码》

 具体流程图如下

 更详细的流程可以查看《Spring-security-oauth2 源码分析 登陆流程 /oauth/token (一)》

 2.集成fegin 以及目录结构

集成fegin 需要的pom
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
 目录结构

 

 注意项

 有fegin 的项目一般都需要分成api 和biz两个module,假如A服务调用B服务的某功能,一定要B服务提供暴漏的feign接口,而不是在A服务去写一个feign 访问B服务的接口,这样设计有两个好处,一是只有B服务自己知道哪些接口可以对外暴漏,可以做些权限限定,二是如果A服务去实现了feign,那以后C服务需要feign访问B服务,C服务还得实现feign,无线增多,会很多代码冗余

 我这里是upms自己提供了自己的feign接口,认证中心引入upms-center-api 注入feign 然后访问我们的用户获取接口

 3.自定义扫面注解注入fegin service

首先看一下我们的自定义注解

package com.minicloud.authentication.annotation;

import org.springframework.cloud.openfeign.EnableFeignClients;

import java.lang.annotation.*;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@EnableFeignClients
public @interface EnableMiniCloudFeignClients {


    String[] value() default {};

    
    String[] basePackages() default {"com.minicloud"};

    Class[] basePackageClasses() default {};

    Class[] defaultConfiguration() default {};

    Class[] clients() default {};


}

可以看见@EnableFeignClients 是我们自定义注解EnableMiniCloudFeignClients 的元注解

,几乎没有区别,只是多了一个package default指定

为什么需要指定package

因为我们是authentication-center服务调用upms-center-biz服务,feign接口并不在authentication-center服务内,如果想注入必须要让spring-boot扫面到这个feign,因为我们的package 外围是com.minicloud,为了方便我就写了这个,以后可能会更细化到子package

 4.设置fegin 传递token header

为什么要设置header

我们调用feign的时候是默认不会讲我们header信息带过去的,所以如果一个接口时有权限的接口

需要手动讲header 带过去,我这里仅仅只赋值token的认证属性,大家可以根据自己需求或者直接将所有header都带过去

package com.minicloud.authentication.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;



public class FeignRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        HttpServletRequest  httpServletRequest =((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
        requestTemplate.header("Authorization",httpServletRequest.getHeader("Authorization"));
    }
}
5.设计某接口只允许feign访问实现原理 为什么要某接口只允许feign调用

有时候我们系统的某个接口不希望前端或者client端可以直接调用,我们只希望是服务和服务之间调用,可以设计一个自定义注解,加上这个注解的接口只允许被feign也就是内部服务之间调用

具体方法有很多,今天主要说一种比较简便的,为了便于理解,画了下图

 大致流程如下:

1.首先我们需要把只允许feign访问的接口加上我们自定义的注解,例如:

2:我们在fegin请求时,自定加上一个专门的自定义 header属性,例如:

  

3:我们需要定义一个拦截器拦截所有被加上这个注解的接口,然后判断到访问这个接口的请求是否包含特定header以及内容是否正常,如果不匹配则抛出异常,如图:

 4:如何防止外部访问模拟出特定header 字段,如上图,我们在网关层会擦除该特定header属性

6.开发只允许fegin注解以及拦截器源码
FeignRequestInterceptor.java
package com.minicloud.authentication.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;



@Component
public class FeignRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        HttpServletRequest  httpServletRequest =((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
        requestTemplate.header("Authorization",httpServletRequest.getHeader("Authorization"));
        requestTemplate.header("feign-request","feign");
    }
}

FeignSecurityAspect.java
package com.minicloud.upms.config;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.access.AccessDeniedException;

import javax.servlet.http.HttpServletRequest;


@Slf4j
@Aspect
@AllArgsConstructor
public class FeignSecurityAspect {

    private final HttpServletRequest request;

    @SneakyThrows
    @Around("@annotation(miniCloudFeignInterface)")
    public Object around(ProceedingJoinPoint point, MiniCloudFeignInterface miniCloudFeignInterface) {
        String header = request.getHeader("feign-request");
        if (StrUtil.equals("feign", header)) {
            log.warn("接口 {} 没有只允许feign访问", point.getSignature().getName());
            throw new AccessDeniedException("Access is denied");
        }
        return point.proceed();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/710492.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号