SpringCloud Gateway + Security + JWT 最快速的集成

这篇具有很好参考价值的文章主要介绍了SpringCloud Gateway + Security + JWT 最快速的集成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

版本

Springboot版本采用的是最新的:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.9</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

网关主要采用的是:文章来源地址https://www.toymoban.com/news/detail-594749.html

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

核心SecurityConfig配置

@EnableWebFluxSecurity
public class SecurityConfig {
    @Autowired
    PermitUrlConfig permitUrlConfig;

    @Autowired
    DefaultSecurityContext defaultSecurityContext;

    @Autowired
    DefaultAuthManager defaultAuthManager;

    @Autowired
    DefaultAccessDecision defaultAccessDecision;

    @Autowired
    DefaultAccessDenied defaultAccessDenied;

    /**
     * 访问权限授权
     *
     * @param http
     * @return
     */
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .csrf().disable()
                .securityContextRepository(defaultSecurityContext)              //认证启动
                .authenticationManager(defaultAuthManager)                      //认证管理
                .authorizeExchange(exchange -> exchange                         //请求拦截处理
                        .pathMatchers(permitUrlConfig.permit()).permitAll()     //默认放开的地址
                        .pathMatchers(HttpMethod.OPTIONS).permitAll()           //放开的请求方法
                        .anyExchange().access(defaultAccessDecision)            //其他的地址走后续验证
                )
                .exceptionHandling().accessDeniedHandler(defaultAccessDenied);  //访问拒绝后执行的处理

        return http.build();
    }
}

定义放开配置的URL

@Component
public class PermitUrlConfig {
    public static final String CONTEXT_PATH = "/gateway";

    /**
     * 需要访问的url
     */
    private String[] permitUrl = {
            "/actuator/**",
            "/api-account/account/**"
    };

    private String[] heartbeatUrl = {
            "/heartbeat/**",
    };

    /**
     * 额外放开权限的url
     *
     * @param urls 自定义的url
     * @return 自定义的url和监控中心需要访问的url集合
     */
    public String[] permit(String... urls) {
        Set<String> set = new HashSet<>();
        if (urls.length > 0) {
            Collections.addAll(set, addContextPath(urls));
        }

        //放开权限的地址
        Collections.addAll(set, addContextPath(permitUrl));
        Collections.addAll(set, heartbeatUrl);

        return set.toArray(new String[set.size()]);
    }

    /**
     * 地址加访问前缀
     * @param urls
     * @return
     */
    private String[] addContextPath(String[] urls) {
        for (int i = 0; i < urls.length; i++) {
            urls[i] = CONTEXT_PATH + urls[i];
        }

        return urls;
    }
}

核心配置中的处理器

DefaultSecurityContext启动认证

@Component
public class DefaultSecurityContext implements ServerSecurityContextRepository {
    @Autowired
    DefaultAuthManager defaultAuthManager;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        String authorization = request.getHeaders().getFirst("Authorization");

        //调用defaultAuthManager的方法
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(authorization, null);
        Mono<Authentication> authenticationMono = defaultAuthManager.authenticate(authenticationToken);

        return authenticationMono.map(SecurityContextImpl::new);
    }
}

DefaultAuthManager执行认证核心方法

@Slf4j
@Component
public class DefaultAuthManager implements ReactiveAuthenticationManager {
    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        String tokenString = (String) authentication.getPrincipal();
        String jwtToken = getJwtToken(tokenString);
        Map<String, Object> authResult = parseToken(jwtToken);

        return Mono.just(authentication).map(auth -> new UsernamePasswordAuthenticationToken(authResult, null, null));
    }

    /**
     * 读取Jwt Token
     *
     * @param authorization
     * @return
     */
    private String getJwtToken(String authorization) {
        if (!StringUtils.hasText(authorization)) {
            return null;
        }

        boolean valid = authorization.startsWith("Bearer ");
        if (!valid) {
            return null;
        }

        return authorization.replace("Bearer ", "");
    }

    /**
     * 校验token
     *
     * @param jwtToken
     * @return
     */
    private Map<String, Object> parseToken(String jwtToken) {
        log.info("[gateway] jwtToken = {}", jwtToken);

        //认证成功
        boolean verify = JwtUtils.verify(jwtToken);
        if (verify) {
            Map<String, Claim> claimMap = JwtUtils.decode(jwtToken);
            Claim claim = claimMap.getOrDefault("data", null);
            if (Objects.nonNull(claim)) {
                return claim.asMap();
            }
        }

        return null;
    }
}

DefaultAccessDecision判断认证后是否放行

@Component
public class DefaultAccessDecision implements ReactiveAuthorizationManager<AuthorizationContext> {
    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext object) {
        Mono<AuthorizationDecision> mono = authentication.map(auth -> {
            Object authResult = auth.getPrincipal();

            //数据读取非空,说明前期在auth的时候,jwt认证返回非空
            if (Objects.nonNull(authResult)) {
                return new AuthorizationDecision(true);
            }

            return new AuthorizationDecision(false);
        });

        return mono;
    }
}

DefaultAccessDenied处理不放行的返回

@Slf4j
@Component
public class DefaultAccessDenied implements ServerAccessDeniedHandler {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.FORBIDDEN);
        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");

        HashMap<String, Object> map = new HashMap<>();
        map.put("code", 400);
        map.put("message", "未授权禁止访问");
        map.put("data", "请检查Token是否合法");
        log.error("[DefaultAccessDenied] access forbidden path={}", exchange.getRequest().getPath());

        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));
        return response.writeWith(Mono.just(dataBuffer));
    }
}

到了这里,关于SpringCloud Gateway + Security + JWT 最快速的集成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微服务多模块:Springboot+Security+Redis+Gateway+OpenFeign+Nacos+JWT (附源码)仅需一招,520彻底拿捏你

      可能有些人会觉得这篇似曾相识,没错,这篇是由原文章进行二次开发的。 前阵子有些事情,但最近看到评论区说原文章最后实现的是单模块的验证,由于过去太久也懒得验证,所以重新写了一个完整的可以跑得动的一个。 OK,回到正题,以下是真正对应的微服务多模块

    2024年02月05日
    浏览(42)
  • SpringCloud nacos 集成 gateway ,实现动态路由

    🎈 作者: Linux猿 🎈 简介: CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! 🎈 欢迎小伙伴们点赞👍、收藏⭐、留言💬 目录 一、准备工作 1.1 下载代码 1.2 运行代码 二、集成 gateway 2.1 修改 pom.xml 2

    2024年02月16日
    浏览(33)
  • SpringCloud Sentinel集成Gateway和实时监控

    想学习架构师构建流程请跳转:Java架构师系统架构设计 参看: https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81#spring-cloud-gateway 我们的项目流量入口是 SpringCloud Gateway ,因此我们重点讲解Sentinel集成 Gateway 。 Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进

    2024年02月09日
    浏览(42)
  • Spring Gateway使用JWT实现统一身份认证

    在开发集群式或分布式服务时,鉴权是最重要的一步,为了方便对请求统一鉴权,一般都是会放在网关中进行处理。目前非常流行的一种方案是使用JWT,详细的使用说明,可以找相关的资料查阅,这里先不进行深入的引用了。主要使用它下面的特性: 它的数据使用JSON格式封

    2024年02月12日
    浏览(45)
  • Spring Gateway + Oauth2 + Jwt网关统一鉴权

    之前文章里说过,分布式系统的鉴权有两种方式,一是在网关进行统一的鉴权操作,二是在各个微服务里单独鉴权。 第二种方式比较常见,代码网上也是很多。今天主要是说第一种方式。 重要前提:需要收集各个接口的uri路径和所需权限列表的对应关系,并存入缓存。 服务

    2024年02月03日
    浏览(46)
  • Gateway中Spring Security6统一处理CORS

    使用了 gateway 微服务作为整体的网关,并且整合了 Spring Security6 ;还有一个system微服务,作为被请求的资源,当浏览器向 gateway 发送请求,请求 system 资源时,遇到 CORS 问题。 于是我在 system 对应的 controller 上加了 @CrossOrigin ,无效;配置 WebMvcConfigurer ,也无效。 后来发现,

    2024年02月20日
    浏览(35)
  • springcloud-gateway集成knife4j

    springcloud-gateway集成knife4j(swagger2) 环境信息 准备工作 微服务集成knife4j 第一步:编写Knife4jApiInfoProperties 第二步:编写配置类Knife4jConfig 第三步:放行相关资源 保证启动了knife4j 网关集成knife4j 编写配置类Knife4jGatewayConfig 测试验证 相关资料 spring-boot:2.6.3 spring-cloud-alibaba:2

    2023年04月09日
    浏览(41)
  • 基于SpringCloud + Oauth2.0 + ShiroRedis + JWT + Gateway + Nacos + Nginx + Vue实现的SaaS数字商城系统

    SaaS的英文全称是Software as a Service,意思是软件即服务 ,是云计算的其中一种服务模式 SaaS是一种通过Internet提供集中托管应用程序的方式,企业用户一般通过客户端或网页来使用,无需购买、安装或维护任何软件及硬件,因此 SaaS应用程序又被称为\\\"基于Web的软件\\\" 或 \\\"托管软件

    2024年01月20日
    浏览(49)
  • 【SpringCloud】微服务技术栈入门3 - Gateway快速上手

    WebFlux gateway 基于 webflux 构建 WebFlux 是基于反应式流概念的响应式编程框架,用于构建异步非阻塞的 Web 应用程序。它支持响应式编程范式,并提供了一种响应式的方式来处理 Web 请求。 与传统的 Servlet API 相比,WebFlux 采用了基于事件驱动的编程模型,不依赖于传统的线程池模

    2024年02月07日
    浏览(39)
  • 微服务动态权限管理方案(Spring Cloud Gateway+Spring Cloud Security)

    微服务认证方案的大体方向是统一在网关层面认证鉴权,微服务只负责业务,和鉴权完全隔离 整体包含以下四个角色 客户端 :需要访问微服务资源 网关 :负责转发、认证、鉴权 OAuth2.0授权服务 :负责认证授权颁发令牌 微服务集合 :提供资源的一系列服务。 这里的客户端

    2024年02月12日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包