回顾:oauth2和 spring cloud alibaba 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方法的重写:限制客户端对认证接口的访问权限。
/*** 定义授权和令牌端点以及令牌服务*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
{endpoints// 请求方式.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)// 指定token存储位置.tokenStore(tokenStore())// 自定义生成令牌.tokenEnhancer(tokenEnhancer)// 用户账号密码认证.userDetailsService(userDetailsService)// 指定认证管理器.authenticationManager(authenticationManager)// 是否重复使用 refresh_token.reuseRefreshTokens(false)// 自定义异常处理.exceptionTranslator(new CustomWebResponseExceptionTranslator());
}
/*** 配置令牌端点(Token Endpoint)的安全约束*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
{oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
}
/*** 配置客户端详情*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
{clients.withClientDetails(clientDetailsService());
}
(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
{"access_token": "f938d0c1-9633-460d-acdd-f0693a6b5f4c","token_type": "bearer","refresh_token": "4baea735-3c0d-4dfd-b826-91c6772a0962","expires_in": 43199,"scope": "web"
}
3、客户端携带access_token通过API网关访问后端服务
4、API网关收到access_token后通过 AuthenticationWebFilter
对access_token认证
5、API网关转发后端请求,后端服务请求Oauth2认证服务器获取当前用户
另外:
典型的授权码模式:
- 第三方应用向资源持有者请求获取资源
- 资源持有者授权给予第三方应用一个许可
- 第三方应用将该许可给予认证服务器进行认证,如果认证成功,返回一个Access Token
- 第三方应用使用该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)加到路由上来,例如:
/*** 路由配置信息* * @author zhongzk*/
@Configuration
public class RouterFunctionConfiguration
{@Autowiredprivate HystrixFallbackHandler hystrixFallbackHandler;@Autowiredprivate ValidateCodeHandler imageCodeHandler;@SuppressWarnings("rawtypes")@Beanpublic RouterFunction routerFunction(){return RouterFunctions.route(RequestPredicates.path("/fallback").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),hystrixFallbackHandler).andRoute(RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),imageCodeHandler);}}
步骤5: 前端通过访问url http://ip:port/code 返回图形验证码,例如在vue中这样定义:
(1)api文件中定义:
// 获取验证码
export function getCodeImg() {return request({url: '/code',method: 'get'})
}
(2)登录页面定义:
<div class="login-code"><img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div>
methods: {getCode() {getCodeImg().then(res => {this.codeUrl = "data:image/gif;base64," + res.img;this.loginForm.uuid = res.uuid;});},
后端的生成验证码的api定义:
/*** 生成验证码*/
@Override
public AjaxResult createCapcha() throws IOException, CaptchaException
{// 生成验证码String capText = producer.createText();String capStr = capText.substring(0, capText.lastIndexOf("@"));String verifyCode = capText.substring(capText.lastIndexOf("@") + 1);BufferedImage image = producer.createImage(capStr);// 保存验证码信息String uuid = IdUtils.simpleUUID();String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;System.out.println("验证码:" + verifyKey);redisService.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);// 转换流信息写出FastByteArrayOutputStream os = new FastByteArrayOutputStream();try{ImageIO.write(image, "jpg", os);}catch (IOException e){return AjaxResult.error(e.getMessage());}AjaxResult ajax = AjaxResult.success();ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;
}
回顾:oauth2和 spring cloud alibaba gateway 整合相关推荐
- Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos /(非阿里组件))
Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos)(非阿里组件) 回溯 Gateway 整合 nacos 方式一(复杂/灵活/常用) 方式 ...
- Spring Cloud Alibaba gateway ribbon 自定义负载均衡规则。发散灰度发布,金丝雀测试等
上一篇介绍了,ribbon的组件.本篇要自己写一个灰度方案.其实就是一个很简单的思维扩散. 需求 前端header请求携带version字段.路由服务根据version去需要对应版本的服务集合,进行或 ...
- Spring Cloud Alibaba 新版本发布:众多期待内容整合打包加入!
点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 在Nacos 1.0.0 Release之后,Spring Cloud Alibaba也终于发布了最新 ...
- 8.Spring Cloud Alibaba教程:整合Seata分布式事务
概述 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务. 更多的介绍可以参考官方文档:Seata快速入门 本篇主要是介绍Spring Cloud Alibaba ...
- Spring Cloud Alibaba基础教程:Sentinel使用Nacos存储规则
点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 通过上一篇<使用Sentinel实现接口限流>的介绍,相信大家对Sentinel已经有了初 ...
- Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流
点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 最近管点闲事浪费了不少时间,感谢网友们的留言提醒. 及时纠正路线,继续跟大家一起学习Spring Cl ...
- 【Spring Cloud Alibaba】(二)微服务调用组件Feign原理+实战
系列目录 [Spring Cloud Alibaba](一)微服务介绍 及 Nacos注册中心实战 本文目录 系列目录 前言 什么是RPC? Feign和OpenFeign都是什么? HTTP调用 v ...
- Spring Cloud Alibaba 之 RPC 消息:Dubbo 与 Nacos 体系如何协同作业
上一节我介绍了什么是 OpenFeign 通信组件,讲解了如何基于 OpenFeign 实现微服务间的高可用通信.本文我们将继续探讨微服务通信话题,了解阿里巴巴自家的 RPC 框架 Dubbo 是如何 ...
- Spring Cloud Alibaba到底坑不坑?
点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 之前我发过一篇<说说我为什么看好Spring Cloud Alibaba>,然后这两天有网 ...
最新文章
- libgdx 3D 测试一
- API 分页设计与实现探讨
- Cocos2d-x 基础元素
- 计算机信息工程专业985,信息工程学院
- Steger算法(Line_Gauss)-光条中心线提取(基于Hessian矩阵)
- ASP.NET 常用语句代码
- 程序员,代码,理想,老男孩
- web测试的基本测试点
- LeetCode-Python-275. H指数 II
- 求职经验贴-描述笔者当时找工作情形
- 如何给微信公众号增加留言功能?
- 关于smtp发信的收件人to cc和bcc
- 淘宝聚划算怎么做?大神导航,一个神奇的网站从此开启大神之路
- 分数怎么约分成最简分数?其实很简单
- 什么是redis??
- SecureFx设置密钥登陆
- 戏剧的一年,记一段劳动仲裁经历
- 素描中的西红柿静物,这种画法才能画出果肉质感~
- 高级信息项目管理师规划
- linux内核 猪头 作用,漫谈Linux内核哈希表(1)