springcloud+nacos+gateway+oauth2小聚会

本文介绍了如何在微服务架构中,利用Spring Security、OAuth2和JWT实现认证授权,通过Nacos作为注册中心,SpringCloudGateway作为网关,构建了一个安全的认证架构,详细讲解了关键组件配置和流程.

在微服务工程中,Nacos作为目前主流的注册中心和配置中心,Spring Cloud Gateway作为目前主流的网关,下面引入spring security+oauth2+jwt作为认证和授权中心,进行简单的聊聊。
一、spring security
Spring Security是java中的安全框架,主要包括认证和授权,通俗讲,认证就是登录,授权就是权限鉴别。

  • 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户;
  • 授权:经过认证后判断当前用户是否有权限进行某个操作;

安全这一块从来都有说不完的话题,一个简单的注册登录很好做,但是你要是考虑到各种各样的攻击,XSS、CSRF 等等,一个简单的注册登录也能做的很复杂。
幸运的是,即使你对各种攻击不太熟悉,只要你用了 Spring Security,就能自动避免掉很多攻击了,因为 Spring Security 已经自动帮我们完成很多防护了。
具体底层原理和流程请参考官网或大佬解读文章。
二、oauth2

  • what

OAuth是一个开放标准,该标准允许用户让第三方应用访问用户在某一应用上存储的私密资源(如头像),而在这个过程无需将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌token,而不是用户名和密码来访问应用上的数据。
OAuth2是OAuth协议的下一版本,但不向下兼容OAuth。

  • why

实际生活中场景,如小区的业主点了一份外卖,但是小区的门禁系统不让外面小哥进入,此时要想外卖小哥进入,只能业主自己下来开门或告知门禁密码。若告知门禁密码,那外卖小哥岂不是可以随意进出小区了,这明显造成了安全隐患。于是就出现了一个授权机制:
1、门禁系统增加一个授权按钮,外卖小哥只需要点击授权按钮呼叫业主
2、业主收到外卖小哥呼叫,做出应答授权
3、门禁系统弹窗一个令牌,有效期30min,在有效期内可以凭借令牌进行小区
4、外卖小哥输入令牌进入小区
令牌和密码的区别:
1、时效不同,令牌是有过期时间的,而密码一般是永久的;
2、权限不同,令牌的权限的有限的,而密码一般是所有权限的;
3、令牌可以撤销,令牌可以撤销,失效就不能用了 ,而密码一般不允许撤销;
在java开发中,OAuth2的出现就是为了解决类似上面场景的问题。

  • how

OAuth2协议提供了4种不同的授权模式:
1、授权码模式,常见的第三方平台登录功能基本都是使用这种模式;
2、简化模式,不需要客户端和服务器参与,直接在浏览器种向授权服务器申请令牌token;
3、密码模式,用户把用户名和密码直接告诉客户端,客户端使用这些信息向授权服务器申请令牌token;如客户端应用和服务提供商是同一家公司,自己做前后端分离登录就可以采用这种模式;
4、客户端模式,客户端使用自己的名誉而不是用户的名义向服务提供者申请授权,严格来说,客户端模式并不能算作OAuth协议要解决问题的一种解决方案;
具体模式的授权过程请参考官网或大佬文章。

三、统一认证和鉴权架构
微服务的认证授权方案,目前大体分为两类:
1、网关只负责转发请求,认证鉴权交给每个微服务控制
2、统一在网关层面进行认证鉴权,微服务只负责业务
目前主流采用第二种方案,通过Spring Cloud Gateway + Spring Security + OAuth2 + Jwt整合进行统一认证鉴权,大致流程如下
在这里插入图片描述
大致分为四个角色,如下:
1、客户端,需要访问微服务资源
2、网关服务,负责转发、认证、鉴权
3、认证授权服务,负责认证授权颁发令牌
4、微服务,提供具体的业务服务

针对上述架构需要3个服务,分别如下:
1、工程前缀-auth,认证授权服务:负责认证和授权;
2、工程前缀-gateway,网关服务:负责校验认证和鉴权;
3、工程前缀-order,订单微服务:处理业务逻辑;
基础是采用Nacos作为注册与发现中心,安全相关的逻辑只存在于认证服务和网关服务中,其他微服务只是单纯的提供服务而没有任何安全相关逻辑。

通过认证授权服务进行统一的认证和授权,然后通过网关服务来统一校验认证和鉴权,此方案目前为主流方案。

四、工程前缀-auth认证授权服务
1、pom依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>
        <dependency>
        	<groupId>com.nimbusds</groupId>
        	<artifactId>nimbus-jose-jwt</artifactId>
        	<version>8.16</version>
    	</dependency>

2、bootstrap-dev.yml配置

spring:
  main:
    allow-circular-references: true
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  cloud:
    nacos:
      # 注册中心
      discovery:
        server-addr: http://localhost:8848
      # 配置中心
      config:
        # 本地启动
        ## server-addr: ${spring.cloud.nacos.discovery.server-addr}
        server-addr: http://localhost:8848
        file-extension: yaml
        #prefix 默认为 spring.application.name 的值
        # 公共配置
        shared-configs[0]:
          data-id: youlai-common.yaml
          refresh: true

3、在jdk的bin目录下使用如下命令生成RSA证书jwt.jks,复制到resource目录下

keytool -genkey -alias jwt -keyalg RSA -keystore jwt.jks

4、认证授权配置

	/**
     * 配置令牌端点(Token Endpoint)的安全约束
     * @param security
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
   
   
        // 自定义异常处理端口
        security.authenticationEntryPoint(customAuthenticationEntryPoint);
        security.accessDeniedHandler(customAccessDeniedHandler);
        security
                // oauth/token_key
                .tokenKeyAccess("permitAll()")
                // oauth/check_token
                .checkTokenAccess("isAuthenticated()")
                // 允许客户表单认证
                .allowFormAuthenticationForClients();
    }

    /**
     * 配置OAuth2客户端
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
   
   
        clients.withClientDetails(customClientDetailsService);
    }

    /**
     * 配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
   
   
        // 密码模式下配置认证管理器AuthenticationManager
        endpoints.authenticationManager(authenticationManager);
        // 设置AccessToken的存储介质tokenStore,默认使用内存当做存储介质
        endpoints.tokenStore(tokenStore);
        // 设置JwtAccessToken转换器
        endpoints.accessTokenConverter(jwtAccessTokenConverter);

        // 自定义token生成
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter, customTokenEnhancer));

        // 配置TokenService参数
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        // token持久化容器
        tokenServices.setTokenStore(endpoints.getTokenStore
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值