当前位置:   article > 正文

回顾:oauth2和 spring cloud alibaba gateway 整合_spring cloud oauth与gateway

spring cloud oauth与gateway

一、oauth2认证中心:登录用户进行认证,生成token, 同时定义受保护的api服务

(一)oauth2的四种认证模式:授权码模式,简化模式,密码模式,客户端模式。其中授权码模式和密码模式用的最多。

      A.OAuth2授权码模式: 我们进入一些第三方应用程序时,无需注册,只需要微信授权登录即可,对于我们的服务不需要存储用户的密码,只要存储认证平台返回的唯一ID和用户信息即可,这就是OAuth2常见的授权码模式,它的特点就是:利用第三方权威平台实现用户身份的认证,当然如果我们的公司里面很多微服务,我们自己也可以专门提取出一个认证中心,这个认证中心就是上面说的权威认证平台的角色,所有的微服务均要到这个认证中心做认证,从而实现了单点登录的功能。

     B、OAuth2密码模式:通过用户账号和密码的输入,到认证中心获取到token,这个token就是标识用户的身份,一个网站平台或者一个APP,它可能有多个微服务组成,有了这个token后,在一段时间内可以任意访问这些微服务提供的相关api接口服务。

(二)常见的系统架构: 认证中心、微服务、客户端(app/web程序等终端)

     客户端:通常就是指应用程序,可能是web或者手机app。

     认证中心:OAuth2做账号认证生成token,这个token可以分两种:jwt token放在Header中,或者普通token放在redis中,当然OAuth2还可以当资源鉴权功能。

     应用服务:即各个微服务,统一由认证中心做认证与api访问授权。

四、如何开发OAuth2认证中心(即认证服务端)功能:验证账号与密码、生成并存储token、检查token、刷新token等工作。

    (1)pom.xml引入spring-cloud-starter-oauth2包,这个包中已经有了spring-cloud-starter-security,所以不需要再单独引入spring-cloud-starter-security。

    (2)配置application.yml:主要redis和数据库的配置,OAuth2的一些表需要用到,例如客户端的配置表(oauth_client_details)。

    (3)配置spring security:主要配置BCryptPasswordEncoder密码加密工具和忽略oauth2本身的api的拦截的内容。

            很多人这个地方会疑惑为什么OAuth2还需要spring security(主要是这个WebSecurityConfigurerAdapter )

                 答:这是因为OAuth2本身也同时是一个资源服务(它要对外暴露检查token的接口等),这就需要引入spring security

 对授权服务本身的资源(即OAuth2本身的一些api) 进行保护,即OAuth2要开放哪些api。通过spring security(它的WebSecurityConfigurerAdapter )和oauth2的互相配合对不同的url进行访问的控制,通常在WebSecurityConfigurerAdapter 的类中WebSecurity可以配置一些忽略拦截的url的定义。

         很多人这个地方还有一个疑惑有了spring security的WebSecurityConfigurerAdapter ,为什么还需要OAuth2的ResourceServerConfigurerAdapter?

              答:WebSecurityConfigurerAdapter主要作用于用户的登录(form login,Basic auth),oauth的一些资源不需要拦截(这个不需要OAuth2保护的url),即设置忽略拦截的url定义,通常就是忽略OAuth2服务自身的一些api 接口的一些定义。

                      ResourceServerConfigurerAdapter: OAuth2保护一些微服务的资源,这些资源需要token验证后才能访问,主要是对client和token的认证。                     

                     ResourceServerConfigurerAdapter优先级高: 如果同时设置了对某一资源的访问控制,会以ResourceServerConfigurerAdapter设置的为准,因为ResourceServerConfigurerAdapter优先级更高,他会优先处理,而WebSecurityConfigurerAdapter会失效

     (4) UserDetailsService的代码实现               

                  核心的覆盖重写实现接口中loadUserByUsername方法,这个覆盖实现主要调用系统管理微服务中的用户api服务获取用户,或者验证用户的,一般与数据库的用户账号表密切关联。  

       (5) 编写AuthServerConfig配置类:

                     主要实现三个configure方法的重写,各个方法中主要对应以下即

                       AuthorizationServerEndpointsConfigurer参数的重写:让它支持password模式,设置用户验证服务,token的redis存储方式等。

       ClientDetailsServiceConfigurer参数的重写:定义各个客户端的约束条件。

                     public void configure(AuthorizationServerSecurityConfigurer方法的重写:限制客户端对认证接口的访问权限。

  1. /**
  2. * 定义授权和令牌端点以及令牌服务
  3. */
  4. @Override
  5. public void configure(AuthorizationServerEndpointsConfigurer endpoints)
  6. {
  7. endpoints
  8. // 请求方式
  9. .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
  10. // 指定token存储位置
  11. .tokenStore(tokenStore())
  12. // 自定义生成令牌
  13. .tokenEnhancer(tokenEnhancer)
  14. // 用户账号密码认证
  15. .userDetailsService(userDetailsService)
  16. // 指定认证管理器
  17. .authenticationManager(authenticationManager)
  18. // 是否重复使用 refresh_token
  19. .reuseRefreshTokens(false)
  20. // 自定义异常处理
  21. .exceptionTranslator(new CustomWebResponseExceptionTranslator());
  22. }
  1. /**
  2. * 配置令牌端点(Token Endpoint)的安全约束
  3. */
  4. @Override
  5. public void configure(AuthorizationServerSecurityConfigurer oauthServer)
  6. {
  7. oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
  8. }
  1. /**
  2. * 配置客户端详情
  3. */
  4. @Override
  5. public void configure(ClientDetailsServiceConfigurer clients) throws Exception
  6. {
  7. clients.withClientDetails(clientDetailsService());
  8. }

   (6)token可以分来两种: jwt token和redisToken两种方案,根据需要选择,我推荐采用redisToken,jwtToken还需要设置一些配置类,同时配置到认证服务的端点上。     

 

二、spring cloud gateway集成oauth2的支持,实现:网关服务、负责请求转发和鉴权功能

主要工作两块:

1.nacos中对于网关服务配置各个微服务的路由转向:

spring:
  redis:
    host: localhost
    port: 6379
    password: 123456
  cloud:
    gateway:
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      routes:
        # 认证中心 ,id在全部路由定义中须要惟一,不能重复
        - id: ebyte-auth
          # lb代表从注册中心获取服务,且已负载均衡方式转发
          uri: lb://ebyte-auth
          # 转发规则定义/oauth/**请求都还转发至微服务ebyte-auth
          predicates:
            - Path=/oauth/**
          filters:
            # 自定义验证码处理过滤器
            - ValidateCodeFilter
            # StripPrefix去除掉上面path的第一个前缀,这个前缀更多是前端的api中定义的(前缀加了微服务的名称),和后端的api不符合
            - StripPrefix=1
        # 系统模块
        - id: ebyte-system
          uri: lb://ebyte-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1

2.定义一些过滤器(结合业务实际,例如权限的控制,验证码等)。

 

3.其它一些相关知识:


 

在网关集成Oauth2.0后,我们的流程架构如上。主要逻辑如下:
1、客户端应用通过api网关请求认证服务器获取access_token http://localhost:8090/auth-service/oauth/token
2、认证服务器返回access_token

  1. {
  2. "access_token": "f938d0c1-9633-460d-acdd-f0693a6b5f4c",
  3. "token_type": "bearer",
  4. "refresh_token": "4baea735-3c0d-4dfd-b826-91c6772a0962",
  5. "expires_in": 43199,
  6. "scope": "web"
  7. }

3、客户端携带access_token通过API网关访问后端服务
file

4、API网关收到access_token后通过 AuthenticationWebFilter 对access_token认证

5、API网关转发后端请求,后端服务请求Oauth2认证服务器获取当前用户

另外:

典型的授权码模式:

  1. 第三方应用向资源持有者请求获取资源
  2. 资源持有者授权给予第三方应用一个许可
  3. 第三方应用将该许可给予认证服务器进行认证,如果认证成功,返回一个Access Token
  4. 第三方应用使用该access token到资源服务器处获取该access token对应的资源(也就是第一步中资源持有者自身的资源)

 

三、spring cloud gateway集成kaptcha图形验证码(后来我改用了第三包easy-captcha的验证码生成包,更省事效果更佳

  步骤1:pom.xml中引入kaptcha包的引用.

  步骤2:定义CaptchaConfig配置类,设置kaptcha图形验证码样式以及生成规则(可以配置自定义的文本的生成器KaptchaTextCreator类)

  步骤3: 定义ValidateCodeHandler, 即验证码的生成

  步骤4:最终的核心就是定义spring cloud gateway的路由配置类RouterFunctionConfiguration,主要把上面的验证码Hander(ValidateCodeHandler)加到路由上来,例如:

  1. /**
  2. * 路由配置信息
  3. *
  4. * @author zhongzk
  5. */
  6. @Configuration
  7. public class RouterFunctionConfiguration
  8. {
  9. @Autowired
  10. private HystrixFallbackHandler hystrixFallbackHandler;
  11. @Autowired
  12. private ValidateCodeHandler imageCodeHandler;
  13. @SuppressWarnings("rawtypes")
  14. @Bean
  15. public RouterFunction routerFunction()
  16. {
  17. return RouterFunctions
  18. .route(RequestPredicates.path("/fallback").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
  19. hystrixFallbackHandler)
  20. .andRoute(RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
  21. imageCodeHandler);
  22. }
  23. }

 

步骤5: 前端通过访问url  http://ip:port/code  返回图形验证码,例如在vue中这样定义:

(1)api文件中定义:

// 获取验证码

  1. export function getCodeImg() {
  2. return request({
  3. url: '/code',
  4. method: 'get'
  5. })
  6. }

(2)登录页面定义:

  1. <div class="login-code">
  2. <img :src="codeUrl" @click="getCode" class="login-code-img"/>
  3. </div>
  1. methods: {
  2. getCode() {
  3. getCodeImg().then(res => {
  4. this.codeUrl = "data:image/gif;base64," + res.img;
  5. this.loginForm.uuid = res.uuid;
  6. });
  7. },

 

后端的生成验证码的api定义:

  1. /**
  2. * 生成验证码
  3. */
  4. @Override
  5. public AjaxResult createCapcha() throws IOException, CaptchaException
  6. {
  7. // 生成验证码
  8. String capText = producer.createText();
  9. String capStr = capText.substring(0, capText.lastIndexOf("@"));
  10. String verifyCode = capText.substring(capText.lastIndexOf("@") + 1);
  11. BufferedImage image = producer.createImage(capStr);
  12. // 保存验证码信息
  13. String uuid = IdUtils.simpleUUID();
  14. String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
  15. System.out.println("验证码:" + verifyKey);
  16. redisService.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
  17. // 转换流信息写出
  18. FastByteArrayOutputStream os = new FastByteArrayOutputStream();
  19. try
  20. {
  21. ImageIO.write(image, "jpg", os);
  22. }
  23. catch (IOException e)
  24. {
  25. return AjaxResult.error(e.getMessage());
  26. }
  27. AjaxResult ajax = AjaxResult.success();
  28. ajax.put("uuid", uuid);
  29. ajax.put("img", Base64.encode(os.toByteArray()));
  30. return ajax;
  31. }

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/84504
推荐阅读
相关标签
  

闽ICP备14008679号