当前位置:   article > 正文

最新版微服务架构鉴权解决方案Spring Cloud Gateway + Oauth2.0+mybatis+mysql+redis+nacos 统一认证和鉴权_微服务鉴权方案

微服务鉴权方案

目录

鉴权架构图 

一、服务列表和技术版本列表

1. 服务列表

2. 技术版本列表

二、Oauth2.0 核心接口和概念简介

1. Oauth2 对外暴露的重要端口(REST API接口)

1) 申请token接口/oauth/token

2) 校验token接口 /oauth/check_token

3) 授权接口/oauth/authorize

2. Oauth2 定义的角色

三、环境搭建

1. 启动Nacos注册中心

2. 创建Oauth2 Server 工程并注册到Nacos

数据库设计 

oauth_client_details

oauth_access_token

 oauth_refresh_token

sys_user

1) pom.xml

2) application.yml

3) 配置授权服务器

4) 配置资源服务器

5) 配置HttpSecurity

6) 集成mybatis基于数据库认证

3. 整合网关gateway

1) 创建一个网关服务实现请求转发到auth-server

2) pom.xml

3) 配置路由

​4) 测试网关转发请求

四、将普通微服务配置为资源服务器由网关统一转发认证

1. 创建user-service

2. 配置资源服务器

3.  配置oauth2 client 统一转发请求

五、统一鉴权的四种模式验证

1. 授权码模式(authorization_code)

2. 简化模式(implicit)

3. 密码模式(password)

4. 客户端模式(client_credentials)


鉴权架构图 

一、服务列表和技术版本列表

1. 服务列表

服务名称说明
nacos-server 服务注册中心,提供服务发现与注册功能。
springcloud-gateway 提供网关服务,网关尽量不做鉴权相关的操作,主要将请求路由到各微服务,实现统一转发请求到授权服务器
oauth2-project 提供授权服务,通过客户端认证模式,将所有从网关转发过来的请求进行认证和授权。
user-service 用户服务,普通微服务,同时也是资源服务器,需要配置鉴权转发。

2. 技术版本列表

名称版本说明
        Java version11为了支持springboot最新版本,使用java 11
spring-boot-starter-parent
org.springframework.boot
2.6.3Spring boot 版本
spring-cloud-dependencies
org.springframework.cloud
2021.0.1Spring Cloud 版本
spring-cloud-alibaba-dependencies
com.alibaba.cloud
2021.0.1.0Spring Cloud Alibaba 版本
spring-cloud-starter-gateway
org.springframework.cloud
3.1.1Gateway 版本
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.cloud
2021.0.1.0Nacos服务发现版本
spring-cloud-loadbalancer
org.springframework.cloud
3.1.1新版本gateway默认不支持 lb转发,因此需要添加此依赖支持与nacos转发的负载均衡
spring-cloud-starter-oauth2
org.springframework.cloud

2.2.4.RELEASE oauth2 安全框架

         nacos-server

2.0.4naocs 注册中心
mysql-connector-java
mysql

5.1.46提供mysql驱动和数据源
mybatis-spring-boot-starter
org.mybatis.spring.boot
2.1.4提供mybatis支持
mybatis-plus-boot-starter
com.baomidou
3.2.0提供mybatis-plus支持
spring-boot-starter-data-redis
org.springframework.boot
2.6.3提供redis支持

二、Oauth2.0 核心接口和概念简介

        oauth2 是一个能由开发者定制的安全框架,我们可以借助oauth2来完成系统应用的授权和认证,从而达到保护应用安全的目的。

1. Oauth2 对外暴露的重要端口(REST API接口)

        oauth2 框架中自了几个重要的API,我们用它前一定要熟悉以下的接口。

1) 申请token接口/oauth/token

        /oauth/token接口在org.springframework.security.oauth2.provider.endpoint里的TokenEndpoint类里, 该接口会以post请求方式对外提供以表单形式的认证方式,通过了就会返回带期限的token。

        通过表单的形式提交, 通过后会返回一个带期限的access_token, 如下用客户端模式去申请token:

2) 校验token接口 /oauth/check_token

        /oauth/check_token接口在org.springframework.security.oauth2.provider.endpoint包里的CheckTokenEndpoint类里,请求方式get和post都可以,可以看到需要一个token参数

         校验成功后会返回客户端信息:

3) 授权接口/oauth/authorize

        /oauth/authorize接口在org.springframework.security.oauth2.provider.endpoint包里的AuthorizationEndpoint, 该接口可用于授权模式的授权操作, 也可用于简化模式的直接申请token。

2. Oauth2 定义的角色

授权服务器: 给具有权限的资源拥有者对应的访问请求授权。

资源服务器: 受保护的资源,可以为静态资源、接口等。

资源拥有者: 具有该系统资源的拥有者,最终受益于用户。

客户端: 与用户和资源、授权服务器沟通的平台,如一个web应用客户端,QQ、微信以第三方形式登录的客户端。


        理解了Oauth2的概念后,我们把注册中心、授权服务器、网关搭起来。 

三、环境搭建

1. 启动Nacos注册中心

可以参考以下文章启动nacos-server

Nacos源码系列(一) 源码编译_Dream_it_possible!的博客-CSDN博客_nacos 源码编译

2. 创建Oauth2 Server 工程并注册到Nacos

数据库设计 

oauth_client_details

oauth2 认证client-id,client-secret,grant_type等信息需要的数据库表。

  1. /*
  2. Navicat Premium Data Transfer
  3. Source Server : win-local
  4. Source Server Type : MySQL
  5. Source Server Version : 50737
  6. Source Host : localhost:3306
  7. Source Schema : oauth2
  8. Target Server Type : MySQL
  9. Target Server Version : 50737
  10. File Encoding : 65001
  11. */
  12. SET NAMES utf8mb4;
  13. SET FOREIGN_KEY_CHECKS = 0;
  14. -- ----------------------------
  15. -- Table structure for oauth_client_details
  16. -- ----------------------------
  17. DROP TABLE IF EXISTS `oauth_client_details`;
  18. CREATE TABLE `oauth_client_details` (
  19. `client_id` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端ID',
  20. `resource_ids` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源ID集合,多个资源时用英文逗号分隔',
  21. `client_secret` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端密匙',
  22. `scope` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端申请的权限范围',
  23. `authorized_grant_types` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端支持的grant_type',
  24. `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '重定向URI',
  25. `authorities` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端所拥有的SpringSecurity的权限值,多个用英文逗号分隔',
  26. `access_token_validity` int(11) NULL DEFAULT NULL COMMENT '访问令牌有效时间值(单位秒)',
  27. `refresh_token_validity` int(11) NULL DEFAULT NULL COMMENT '更新令牌有效时间值(单位秒)',
  28. `additional_information` varchar(4096) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '预留字段',
  29. `autoapprove` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户是否自动Approval操作',
  30. PRIMARY KEY (`client_id`) USING BTREE
  31. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '客户端信息' ROW_FORMAT = Dynamic;
  32. -- ----------------------------
  33. -- Records of oauth_client_details
  34. -- ----------------------------
  35. INSERT INTO `oauth_client_details` VALUES ('client-app', NULL, '$2a$10$ABFuX9AEpqlGdgJfTrevb.J.5oAx18R7nKOENj13EBtGrYEvkrUoa', 'all', 'password,refresh_token,client_credentials,authorization_code,implicit', 'http://127.0.0.1:9010/dashboard', NULL, 3600, 604800, NULL, '1');
  36. SET FOREIGN_KEY_CHECKS = 1;

oauth_access_token

该表是存放客户端token 信息的表, 生成token时落库,验证时从该表里取出验证。

  1. /*
  2. Navicat Premium Data Transfer
  3. Source Server : win-local
  4. Source Server Type : MySQL
  5. Source Server Version : 50737
  6. Source Host : localhost:3306
  7. Source Schema : oauth2
  8. Target Server Type : MySQL
  9. Target Server Version : 50737
  10. File Encoding : 65001
  11. */
  12. SET NAMES utf8mb4;
  13. SET FOREIGN_KEY_CHECKS = 0;
  14. -- ----------------------------
  15. -- Table structure for oauth_access_token
  16. -- ----------------------------
  17. DROP TABLE IF EXISTS `oauth_access_token`;
  18. CREATE TABLE `oauth_access_token` (
  19. `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'MD5加密的access_token的值',
  20. `token` blob NULL COMMENT 'OAuth2AccessToken.java对象序列化后的二进制数据',
  21. `authentication_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'MD5加密过的username,client_id,scope',
  22. `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录的用户名',
  23. `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端ID',
  24. `authentication` blob NULL COMMENT 'OAuth2Authentication.java对象序列化后的二进制数据',
  25. `refresh_token` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'MD5加密后的refresh_token的值',
  26. PRIMARY KEY (`authentication_id`) USING BTREE
  27. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '访问令牌' ROW_FORMAT = Dynamic;
  28. -- ----------------------------
  29. -- Records of oauth_access_token
  30. -- ----------------------------
  31. INSERT INTO `oauth_access_token` VALUES ('cfd26bb25194ad1ae6fe1a2b759c7ba6', 0xACED0005737200436F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F4175746832416363657373546F6B656E0CB29E361B24FACE0200064C00156164646974696F6E616C496E666F726D6174696F6E74000F4C6A6176612F7574696C2F4D61703B4C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B4C000C72656672657368546F6B656E74003F4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F636F6D6D6F6E2F4F417574683252656672657368546F6B656E3B4C000573636F706574000F4C6A6176612F7574696C2F5365743B4C0009746F6B656E547970657400124C6A6176612F6C616E672F537472696E673B4C000576616C756571007E000578707372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794D6170593614855ADCE7D002000078707372000E6A6176612E7574696C2E44617465686A81014B597419030000787077080000018079CB3BD3787372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E71007E0002787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C756571007E0005787074002431643465383931652D343737362D346138362D623966372D6330643132623732376430347371007E00097708000001809DA0D15278737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F40000000000001740003616C6C7874000662656172657274002430393934333030612D633966632D346233382D393732392D383761663261326562366462, '702834532a7bab38cab035bd2e8c3fee', NULL, 'client-app', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A657870000000007704000000007871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B72656469726563745572697400124C6A6176612F6C616E672F537472696E673B4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0011787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000F4C001172657175657374506172616D657465727371007E000E4C000573636F706571007E0011787074000A636C69656E742D617070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E000E7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000037708000000040000000274000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F696474000A636C69656E742D61707078737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F40000000000001740003616C6C78017371007E0020770C000000103F40000000000000787371007E00173F40000000000000770800000010000000007870707371007E0020770C000000103F40000000000000787371007E0020770C000000103F400000000000007870, '1bcc81c9038d7305e2ca339a9a3732db');
  32. SET FOREIGN_KEY_CHECKS = 1;

 oauth_refresh_token

        刷新token的记录表, token_id字段与oauth_access_token的refresh_token字段关联。

  1. /*
  2. Navicat Premium Data Transfer
  3. Source Server : win-local
  4. Source Server Type : MySQL
  5. Source Server Version : 50737
  6. Source Host : localhost:3306
  7. Source Schema : oauth2
  8. Target Server Type : MySQL
  9. Target Server Version : 50737
  10. File Encoding : 65001
  11. */
  12. SET NAMES utf8mb4;
  13. SET FOREIGN_KEY_CHECKS = 0;
  14. -- ----------------------------
  15. -- Table structure for oauth_refresh_token
  16. -- ----------------------------
  17. DROP TABLE IF EXISTS `oauth_refresh_token`;
  18. CREATE TABLE `oauth_refresh_token` (
  19. `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'MD5加密过的refresh_token的值',
  20. `token` blob NULL COMMENT 'OAuth2RefreshToken.java对象序列化后的二进制数据',
  21. `authentication` blob NULL COMMENT 'OAuth2Authentication.java对象序列化后的二进制数据'
  22. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '更新令牌' ROW_FORMAT = Dynamic;
  23. -- ----------------------------
  24. -- Records of oauth_refresh_token
  25. -- ----------------------------
  26. INSERT INTO `oauth_refresh_token` VALUES ('1bcc81c9038d7305e2ca339a9a3732db', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002431643465383931652D343737362D346138362D623966372D6330643132623732376430347372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001809DA0D15278, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A657870000000007704000000007871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B72656469726563745572697400124C6A6176612F6C616E672F537472696E673B4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0011787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000F4C001172657175657374506172616D657465727371007E000E4C000573636F706571007E0011787074000A636C69656E742D617070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E000E7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000037708000000040000000274000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F696474000A636C69656E742D61707078737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F40000000000001740003616C6C78017371007E0020770C000000103F40000000000000787371007E00173F40000000000000770800000010000000007870707371007E0020770C000000103F40000000000000787371007E0020770C000000103F400000000000007870);
  27. INSERT INTO `oauth_refresh_token` VALUES ('4c64de4ee4fe5845c6b793c58f39292b', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002464333337666233332D366462642D343563332D623138372D3265303164623539323065307372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001809DC0526778, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A657870000000007704000000007871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B72656469726563745572697400124C6A6176612F6C616E672F537472696E673B4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0011787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000F4C001172657175657374506172616D657465727371007E000E4C000573636F706571007E0011787074000A636C69656E742D617070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E000E7870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F7479706574000870617373776F7264740009636C69656E745F696474000A636C69656E742D617070740008757365726E616D6574000462696E6778737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F40000000000001740003616C6C78017371007E0022770C000000103F40000000000000787371007E00173F40000000000000770800000010000000007870707371007E0022770C000000103F40000000000000787371007E0022770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000002300200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B000000007704000000007871007E002C737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E00173F400000000000067708000000080000000474000D636C69656E745F73656372657474001161736466686F6C7531326A6F736164662371007E001971007E001A71007E001B71007E001C71007E001D71007E001E780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000002300200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00114C000870617373776F726471007E000F4C0008757365726E616D6571007E000F7870010101017371007E001F737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000002300200007870770400000000787071007E001E);
  28. SET FOREIGN_KEY_CHECKS = 1;

sys_user

        系统用户表, 主要包含用户信息,密码采用BCryptPasswordEncoder加密方法encode后的结果。

  1. /*
  2. Navicat Premium Data Transfer
  3. Source Server : win-local
  4. Source Server Type : MySQL
  5. Source Server Version : 50737
  6. Source Host : localhost:3306
  7. Source Schema : oauth2
  8. Target Server Type : MySQL
  9. Target Server Version : 50737
  10. File Encoding : 65001
  11. */
  12. SET NAMES utf8mb4;
  13. SET FOREIGN_KEY_CHECKS = 0;
  14. -- ----------------------------
  15. -- Table structure for sys_user
  16. -- ----------------------------
  17. DROP TABLE IF EXISTS `sys_user`;
  18. CREATE TABLE `sys_user` (
  19. `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  20. `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  21. `pass_word` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  22. `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  23. `sex` int(2) NULL DEFAULT NULL,
  24. `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  25. `enable` int(2) NULL DEFAULT NULL,
  26. `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  27. `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  28. `create_time` datetime(0) NULL DEFAULT NULL,
  29. `account_expired` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '账号是否失效',
  30. `account_locked` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '账号是否被锁定',
  31. PRIMARY KEY (`id`) USING BTREE,
  32. UNIQUE INDEX `user_name`(`user_name`) USING BTREE
  33. ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
  34. -- ----------------------------
  35. -- Records of sys_user
  36. -- ----------------------------
  37. INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$gHF4b6c.Z4LrSqly3kpLwegXzBo6Q1TtBQlcrXt6Lctu/aLAZlPQe', 'bingbing', 1, '123', 1, '123456@qq.com', '', '2022-04-28 11:02:15', 0, 0);
  38. INSERT INTO `sys_user` VALUES (2, 'bing', '$2a$10$FgJjpqW0WihRn/aYXxh8QuO0vp2iGK268H/G8VmbF5kRXeK5b23UG', 'bing', 1, '131', 1, '', '', '2022-04-28 18:25:32', 0, 0);
  39. INSERT INTO `sys_user` VALUES (3, 'test01', '4b15d2b3b671209e01202331881af5a6044d342dc624d29a53ed6b4402af6d61', 'test', 1, '2312', 1, '1212', NULL, NULL, 0, 0);
  40. SET FOREIGN_KEY_CHECKS = 1;

1) pom.xml

        核心依赖: spring-cloud-starter-oauth2, 版本尽量选择较新的。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>com.bing.cloud</groupId>
  7. <artifactId>oauth2-project</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <artifactId>oauth2-server</artifactId>
  11. <version>0.0.1-SNAPSHOT</version>
  12. <name>oauth2-server</name>
  13. <description>Demo project for Spring Boot</description>
  14. <properties>
  15. <java.version>11</java.version>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-starter-web</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-jdbc</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-actuator</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>mysql</groupId>
  32. <artifactId>mysql-connector-java</artifactId>
  33. <version>5.1.46</version>
  34. </dependency>
  35. <!-- redis-->
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-data-redis</artifactId>
  39. </dependency>
  40. <!--整合mybatis-->
  41. <dependency>
  42. <groupId>org.mybatis.spring.boot</groupId>
  43. <artifactId>mybatis-spring-boot-starter</artifactId>
  44. <version>2.1.4</version>
  45. </dependency>
  46. <!-- mybatis-plus插件-->
  47. <dependency>
  48. <groupId>com.baomidou</groupId>
  49. <artifactId>mybatis-plus-boot-starter</artifactId>
  50. <version>3.2.0</version>
  51. </dependency>
  52. <!--集成druid连接池-->
  53. <dependency>
  54. <groupId>com.alibaba</groupId>
  55. <artifactId>druid-spring-boot-starter</artifactId>
  56. <version>1.1.10</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>org.springframework.boot</groupId>
  60. <artifactId>spring-boot-starter-test</artifactId>
  61. <scope>test</scope>
  62. </dependency>
  63. <dependency>
  64. <groupId>junit</groupId>
  65. <artifactId>junit</artifactId>
  66. <scope>test</scope>
  67. </dependency>
  68. <dependency>
  69. <groupId>org.projectlombok</groupId>
  70. <artifactId>lombok</artifactId>
  71. </dependency>
  72. <dependency>
  73. <groupId>com.alibaba.cloud</groupId>
  74. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  75. </dependency>
  76. <!--security -->
  77. <dependency>
  78. <groupId>org.springframework.cloud</groupId>
  79. <artifactId>spring-cloud-starter-oauth2</artifactId>
  80. <version>2.2.4.RELEASE</version>
  81. </dependency>
  82. <dependency>
  83. <groupId>com.google.code.gson</groupId>
  84. <artifactId>gson</artifactId>
  85. </dependency>
  86. </dependencies>
  87. <build>
  88. <plugins>
  89. <plugin>
  90. <groupId>org.springframework.boot</groupId>
  91. <artifactId>spring-boot-maven-plugin</artifactId>
  92. </plugin>
  93. <plugin>
  94. <artifactId>maven-compiler-plugin</artifactId>
  95. <configuration>
  96. <source>${java.version}</source>
  97. <target>${java.version}</target>
  98. </configuration>
  99. </plugin>
  100. </plugins>
  101. </build>
  102. </project>

2) application.yml

        配置mysql数据源、nacos 注册中心、redis、mybatis, 注意配置spring.application.name, spring.application.name作为微服务名字注册到nacos里。

  1. server:
  2. port: 9010
  3. servlet:
  4. context-path: /
  5. spring:
  6. application:
  7. name: oauth2-server-service
  8. datasource:
  9. driver-class-name: com.mysql.jdbc.Driver
  10. url: jdbc:mysql://localhost:3306/oauth2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
  11. username: root
  12. password: root
  13. cloud:
  14. nacos:
  15. discovery:
  16. server-addr: localhost:8848
  17. username: nacos
  18. password: nacos
  19. redis:
  20. host: localhost
  21. port: 6379
  22. password: redis#847652.
  23. database: 0
  24. management:
  25. endpoints:
  26. web:
  27. exposure:
  28. include: "*"
  29. #mybatis
  30. mybatis:
  31. mapper-locations:
  32. - classpath:mapper/*.xml
  33. - classpath:com/**/mapper/*.xml
  34. # myabtis-domain
  35. mybatis-plus:
  36. type-aliases-package: com.bing.cloud.**.entity

3) 配置授权服务器

  • 配置ClientDetailService, 使一些配置支持从数据库表oauth_client_details读取。
  • 配置自定义的userDetailService, 通过实现UserDetailsService接口创建。
  • 配置JdbcTokenStore, 将生成的token落库,如果不配置,那么在生成token和验证token时会默认使用InMemoryTokenStore, 生成的token会存放在一个accessTokenStore的concurrentHashMap里,也就是说默认是基于内存认证的,我们可以通过配置JdbcTokenStore基于数据库认证,如果采用此方式,必须要用到oauth_access_token表。
  • TokenStore也可以选择使用RedisTokenStore, redis 速度会比内存更高效,tokenStore只能选择一种
  • 配置允许使用表单认证,.tokenKeyAccess("permitAll()") .checkTokenAccess("permitAll()"), 如果没有该配置,通过网关访问user-service转发请求/oauth/check_token的时候会出现403的问题。
  1. package com.bing.cloud.config;
  2. import com.bing.cloud.service.impl.CustomUserDetailServiceImpl;
  3. import lombok.AllArgsConstructor;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.data.redis.connection.RedisConnectionFactory;
  8. import org.springframework.security.authentication.AuthenticationManager;
  9. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  10. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  11. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
  12. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
  13. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
  14. import org.springframework.security.oauth2.provider.ClientDetailsService;
  15. import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
  16. import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
  17. import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
  18. import javax.sql.DataSource;
  19. /**
  20. * 认证服务器配置
  21. */
  22. @AllArgsConstructor
  23. @Configuration
  24. @EnableAuthorizationServer
  25. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  26. private final CustomUserDetailServiceImpl userDetailsService;
  27. private final AuthenticationManager authenticationManager;
  28. // private final PasswordEncoder passwordEncoder;
  29. @Autowired
  30. private DataSource dataSource;
  31. @Autowired
  32. private RedisConnectionFactory redisConnectionFactory;
  33. /**
  34. * 基于数据库认证
  35. *
  36. * @return
  37. */
  38. @Bean
  39. public ClientDetailsService customClientDetailsService() {
  40. return new JdbcClientDetailsService(dataSource);
  41. }
  42. /**
  43. * token 落库
  44. *
  45. * @return
  46. */
  47. public JdbcTokenStore jdbcTokenStore() {
  48. return new JdbcTokenStore(dataSource);
  49. }
  50. public RedisTokenStore redisTokenStore(){
  51. return new RedisTokenStore(redisConnectionFactory);
  52. }
  53. @Override
  54. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  55. clients.withClientDetails(customClientDetailsService());
  56. // 由于配置了JDBCClient, 因此会去查询数据库oauth_client_details,因此下面的配置可以不需要
  57. // .withClient("client-app")
  58. // .secret(passwordEncoder.encode("asdfholu12josadf#"))
  59. // .autoApprove(true)
  60. // .redirectUris("http://127.0.0.1:9010/dashboard")
  61. // .scopes("all")
  62. // .authorizedGrantTypes("password", "implicit", "client_credentials", "authorization_code","refresh_token")
  63. // .accessTokenValiditySeconds(3600)
  64. // .refreshTokenValiditySeconds(86400);
  65. }
  66. @Override
  67. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  68. //配置加载用户信息的服务
  69. // token 落库
  70. endpoints.authenticationManager(authenticationManager)
  71. .userDetailsService(userDetailsService)
  72. .tokenStore(redisTokenStore())
  73. ;
  74. }
  75. /**
  76. * 解决访问/oauth/check_token 403的问题
  77. *
  78. * @param security
  79. * @throws Exception
  80. */
  81. @Override
  82. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  83. // 允许表单认证
  84. security
  85. .tokenKeyAccess("permitAll()")
  86. .checkTokenAccess("permitAll()")
  87. .allowFormAuthenticationForClients();
  88. }
  89. }

4) 配置资源服务器

        auth-server-service对外提供的api也可以看做资源,同样支持授权和认证。

  1. package com.bing.cloud.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  4. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
  5. import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
  6. /**
  7. * 资源服务器配置
  8. */
  9. @Configuration
  10. @EnableResourceServer
  11. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  12. @Override
  13. public void configure(HttpSecurity http) throws Exception {
  14. http.authorizeRequests()
  15. .anyRequest()
  16. .authenticated()
  17. .and()
  18. .requestMatchers()
  19. .antMatchers("/api/**");//配置需要保护的资源路径
  20. }
  21. }

5) 配置HttpSecurity

        可以在WebSecurityConfigurerAdapter里configure方法里配置不需要拦截的url, 比如一些登录、登出地址, 默认登录页面用 .formLogin()。

  1. package com.bing.cloud.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.authentication.AuthenticationManager;
  5. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  7. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  8. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  9. import org.springframework.security.crypto.password.PasswordEncoder;
  10. /**
  11. * SpringSecurity配置
  12. */
  13. @Configuration
  14. @EnableWebSecurity
  15. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  16. @Bean
  17. public PasswordEncoder passwordEncoder() {
  18. return new BCryptPasswordEncoder();
  19. }
  20. @Bean
  21. @Override
  22. public AuthenticationManager authenticationManagerBean() throws Exception {
  23. return super.authenticationManagerBean();
  24. }
  25. @Override
  26. public void configure(HttpSecurity http) throws Exception {
  27. http.csrf()
  28. .disable()
  29. .httpBasic()
  30. .and()
  31. .authorizeRequests()
  32. // 配置可以直接访问的页面
  33. .antMatchers("/login/**", "/logout/**", "/api/getCurrentUser")
  34. .permitAll()
  35. // 其余所有请求都要通过认证鉴权
  36. .anyRequest()
  37. .authenticated()
  38. .and()
  39. // 配置spring security默认的登录页面
  40. .formLogin()
  41. .permitAll();
  42. }
  43. }

6) 集成mybatis基于数据库认证

        当使用密码模式请求/oauth/token接口时,我们可以使用自己创建的数据库与oauth2进行集成,只需要重写UserDetailService里的loadUserByUserName(String username)方法即可。

        创建SecurityUser对象,使用mybatisplus插件映射到sys_user表。

  1. package com.bing.cloud.service.impl;
  2. import com.bing.cloud.MessageConstant;
  3. import com.bing.cloud.entity.SecurityUser;
  4. import com.bing.cloud.service.UserService;
  5. import com.google.gson.GsonBuilder;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.security.authentication.AccountExpiredException;
  8. import org.springframework.security.authentication.DisabledException;
  9. import org.springframework.security.authentication.LockedException;
  10. import org.springframework.security.core.authority.AuthorityUtils;
  11. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  12. import org.springframework.security.core.userdetails.User;
  13. import org.springframework.security.core.userdetails.UserDetails;
  14. import org.springframework.security.core.userdetails.UserDetailsService;
  15. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  16. import org.springframework.security.crypto.password.PasswordEncoder;
  17. import org.springframework.stereotype.Service;
  18. import javax.annotation.PostConstruct;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. /**
  22. * 自定义用户服务
  23. */
  24. @Service
  25. public class CustomUserDetailServiceImpl implements UserDetailsService {
  26. @Autowired
  27. private UserService userService;
  28. @Override
  29. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  30. // 基于数据库认证
  31. SecurityUser userInfo = userService.selectUserByUserName(username);
  32. if (!userInfo.isEnabled()) {
  33. throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
  34. } else if (userInfo.isAccountLocked()) {
  35. throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
  36. } else if (userInfo.isAccountExpired()) {
  37. throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
  38. }
  39. // 获取到所有的role, 把role写入到simpleGrantedAuthority里。
  40. List<SimpleGrantedAuthority> authorities = new ArrayList<>();
  41. // String password = passwordEncoder.encode(userInfo.getPassword());
  42. return new User(username, userInfo.getPassword(), authorities);
  43. }
  44. }

        如果需要配置一些role, 可以通过mybatis将role表里的角色添加到SimpleGrantedAuthority列表里。

        上述操作如果无误后启动 Auth-Server,能在nacos 里发现注册成功即可。

3. 整合网关gateway

        如果还有不了解gateway的朋友,推荐抽点时间浏览一下以下的文章

微服务架构网关组件Spring Cloud Gateway 用法详解和实战案例_Dream_it_possible!的博客-CSDN博客

1) 创建一个网关服务实现请求转发到auth-server

        本节目标是创建一个网关服务,实现请求能通过nacos转发到auth-server服务器上。

        网关的作用是为了统一请求的入口,因此不建议在网关里写入大量的鉴权逻辑,新建一个springboot工程

2) pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.3</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.example.gateway</groupId>
  12. <artifactId>cloud-gateway</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>cloud-gateway</name>
  15. <description>project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. <java.version>11</java.version>
  19. <docker.registry.url>116.62.146.90</docker.registry.url>
  20. <docker.namespace>my-shop</docker.namespace>
  21. <spring-cloud.version>2021.0.1</spring-cloud.version>
  22. <spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
  23. </properties>
  24. <dependencies>
  25. <dependency>
  26. <groupId>org.springframework.cloud</groupId>
  27. <artifactId>spring-cloud-starter-gateway</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
  32. </dependency>
  33. <!--整合断路器-->
  34. <dependency>
  35. <groupId>org.springframework.cloud</groupId>
  36. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  37. <version>2.2.4.RELEASE</version>
  38. </dependency>
  39. <!-- 添加eureka客户端-->
  40. <!-- <dependency>-->
  41. <!-- <groupId>org.springframework.cloud</groupId>-->
  42. <!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
  43. <!-- </dependency>-->
  44. <dependency>
  45. <groupId>com.alibaba.cloud</groupId>
  46. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  47. </dependency>
  48. <dependency>
  49. <groupId>org.springframework.boot</groupId>
  50. <artifactId>spring-boot-starter-test</artifactId>
  51. <scope>test</scope>
  52. </dependency>
  53. </dependencies>
  54. <dependencyManagement>
  55. <dependencies>
  56. <dependency>
  57. <groupId>org.springframework.cloud</groupId>
  58. <artifactId>spring-cloud-dependencies</artifactId>
  59. <version>${spring-cloud.version}</version>
  60. <type>pom</type>
  61. <scope>import</scope>
  62. </dependency>
  63. <dependency>
  64. <groupId>com.alibaba.cloud</groupId>
  65. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  66. <version>${spring.cloud.alibaba.version}</version>
  67. <type>pom</type>
  68. <scope>import</scope>
  69. </dependency>
  70. </dependencies>
  71. </dependencyManagement>
  72. <build>
  73. <finalName>my-gateway</finalName>
  74. <resources>
  75. <resource>
  76. <directory>src/main/java</directory>
  77. <includes>
  78. <include>**/*.xml</include>
  79. </includes>
  80. </resource>
  81. <resource>
  82. <directory>src/main/resources</directory>
  83. </resource>
  84. </resources>
  85. <plugins>
  86. <plugin>
  87. <groupId>org.springframework.boot</groupId>
  88. <artifactId>spring-boot-maven-plugin</artifactId>
  89. </plugin>
  90. <plugin>
  91. <groupId>com.spotify</groupId>
  92. <artifactId>dockerfile-maven-plugin</artifactId>
  93. <version>1.4.13</version>
  94. <executions>
  95. <execution>
  96. <id>build_image</id>
  97. <phase>package</phase>
  98. <goals>
  99. <!--如果package时不想用docker打包,就注释掉这个goal -->
  100. <goal>build</goal>
  101. <goal>push</goal>
  102. </goals>
  103. </execution>
  104. </executions>
  105. <configuration>
  106. <contextDirectory>${project.basedir}</contextDirectory>
  107. <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
  108. <repository>${docker.registry.url}/${docker.namespace}/${project.artifactId}</repository>
  109. <tag>${project.version}</tag>
  110. <buildArgs>
  111. <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
  112. </buildArgs>
  113. </configuration>
  114. </plugin>
  115. </plugins>
  116. </build>
  117. </project>

3) 配置路由

        添加auth-service-routte路由,注意将uri设置为lb://oauth2-server-service,因为通过nacos转发时,会根据服务名进行负载均衡式的请求。

        可以在predicates里配置StripPrefix=1, 转发到目标服务后会去掉Path里第一个"/"和第二个"/"里的内容。

  1. server:
  2. port: 9000
  3. spring:
  4. application:
  5. name: gateway
  6. cloud:
  7. gateway:
  8. discovery:
  9. locator:
  10. enabled: true
  11. lower-case-service-id: true
  12. routes:
  13. - id: user-service #路由的ID
  14. uri: lb://user-service
  15. predicates:
  16. - Method=GET,POST
  17. - Path=/user/**
  18. filters:
  19. - StripPrefix=1
  20. - name: Retry
  21. args:
  22. retires: 1
  23. statuses: BAD_GATEWAY
  24. - id: auth-service-route
  25. uri: lb://oauth2-server-service
  26. predicates:
  27. - Method=GET,POST
  28. - Path=/auth-server/**
  29. filters:
  30. - name: Retry
  31. args:
  32. retries: 1 # 调用失败需要进行重试的次数,比如因为网络原因出现502
  33. statuses: BAD_GATEWAY
  34. - StripPrefix=1
  35. nacos:
  36. server-addr: localhost:8848
  37. discovery:
  38. server-addr: ${spring.cloud.nacos.server-addr}
  39. username: nacos
  40. password: nacos
  41. namespace: public
  42. logging:
  43. level:
  44. org.springframework.cloud.gateway: debug

启动网关服务, 可以从控制台看到我们配置的路由和相关的规则。

4) 测试网关转发请求

        首先在auth-server添加一个测试api:  /api/hello,使用postman访问请求localhost:9000/auth-server/api/hello。

        解决用网关转发Lb时,一直报503的问题: 

        由于最新版spring cloud的gateway不支持负载均衡功能,因此需要手动添加一个loadbalancer依赖:

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-loadbalancer</artifactId>
  4. </dependency>

        重新刷新依赖、启动网关微服务,访问localhost:9000/auth-server/api/hello,响应代码为: 401, 说明请求正确的转发到auth-server:

        在一个大型的分布式系统里,存在的微服务可能有几十个或者上百个,如何使用网关和oauth server来保护,我们可以将普通微服务的未认证的请求全部由网关转发给鉴权服务器。

四、将普通微服务配置为资源服务器由网关统一转发认证

1. 创建user-service

        同样集成nacos, oauth2,mybatis 等框架,运行起来后能在nacos中发现。

2. 配置资源服务器

        放了方便配置资源服务器,我们将所有需要认证的接口都带上/api前缀。

  1. package com.bingbing.sh.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  4. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
  5. import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
  6. /**
  7. * 资源服务器配置
  8. */
  9. @Configuration
  10. @EnableResourceServer
  11. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  12. @Override
  13. public void configure(HttpSecurity http) throws Exception {
  14. http.authorizeRequests()
  15. .anyRequest()
  16. .authenticated()
  17. .and()
  18. .requestMatchers()
  19. .antMatchers("/api/**");//配置需要保护的资源路径
  20. }
  21. }

3.  配置oauth2 client 统一转发请求

        需要注意client-id和client-secret要与数据库里保持一致,可以选择使用客户端模式的进行认证,另外ecurity.oauth2.resource.token-info-uri这个值配为:oauth2-server的/oauth/check_token。

        在application.properties文件里添加以下配置:

  1. security.oauth2.client.access-token-uri=http://localhost:9000/auth-server/oauth/token
  2. security.oauth2.client.client-authentication-scheme=form
  3. security.oauth2.client.client-id=client-app
  4. security.oauth2.client.client-secret=asdfholu12josadf#
  5. security.oauth2.client.grant-type=client_credentials
  6. security.oauth2.resource.token-info-uri=http://localhost:9000/auth-server/oauth/check_token
        我们在请求user-service里的接口时,可以跟踪一下源代码,看一下oauth2 在user-service做了哪些事?
        首先把上述的properties里的配置给注释掉,进入OAuth2AuthenticationProcessingFilter在 org.springframework.security.oauth2.provider.authentication 包里。 .doFilter() 方法, doFilter()方法用来拦截进入的请求。

        接着进入到OAuth2AuthenticationManager.authenticate方法:

然后进入到tokenServices.loadAuthentication()方法: 

默认进入到DefaultTokenService里的loadAuthentication:

        可以发现默认是进入到DefaultTokenService认证token的,我们可以推断出肯定是不行的,因为我在user-service的项目里没有配置授权服务器,简单讲user-service是没有授权功能的。

        接着我们把注释的配置放开,然后进入到loadAuthentication方法,发现是通过RemoteTokenServices调用的,向我们配置的security.oauth2.resource.token-info-uri 地址发起了一个rest请求:

        如果token是正确的话,/oauth/check_token接口会返回一个map给我们

五、统一鉴权的四种模式验证

        我们需要基于数据库的进行认证,那么需要在数据库里也配置所有的授权模式。

        在authorized_grant_types字段里配置4种模式,用"," 隔开: password,client_credentials,authorization_code,implicit,在配置可以在加一个refresh_token,用于支持刷新token。

1. 授权码模式(authorization_code)

        授权码模式是现在最严密、最安全的一种认证模式,第三方应用先通过登录获取到一个授权码和directUrl, 然后携带授权码和directUrl去授权服务器请求token令牌, 其中direct_url配置在数据库里,参数中的grant_type为client_credentials。

        第一步在浏览器中访问如下地址:

 http://localhost:9010/oauth/authorize?client_id=client-app&client_secret=asdfholu12josadf%23&response_type=code

        输入用户名和密码:

         登录成功后会在地址栏上返回一个code,每次申请的code只能使用一次, 由于我没有配置/dashboard页面,因此会报404的错误:

         拿到code后,使用postman采用授权码模式请求token:

         再次用同样的code去请求就会报错:Invalid authorization code: n2jZMX,必须重新访问/oauth/authorize重新申请一个新的code才行。

2. 简化模式(implicit)

        简化模式是直接在浏览器中向授权服务器申请令牌,成功了就能拿到token,参数中的grant_type为token。

        第一步在浏览器中输入:

localhost:9010/oauth/authorize?grant_type=implicit&client_id=client-app&scope=all&redirect_uri=http://127.0.0.1:9010/dashboard&response_type=token

        其中 redirect_uri和grant_type均配置在数据库里,如果没有登录,那么会先输入用户名和密码,登录成功后,会在地址栏上显示出token和失效时间。

3. 密码模式(password)

        密码模式是用户向客户端提供用户名和密码,客户端使用这些信息向授权服务器去申请令牌,参数中的grant_type为password,需要客户端应用与服务器提供商高度信息,必须是同一家公司。

        密码模式直接将客户端ID、secret、用户名和密码放在body的表单里,用postman发一个post请求。

localhost:9010/oauth/token

        body里的参数 

grant_type:password
client_id:client-app
client_secret:asdfholu12josadf#
username:bing
password:123456

4. 客户端模式(client_credentials)

        客户端模式是指客户端用自己的名义而不是用户的身份去向授权服务器申请令牌。

        用postman请求localhost:9010/oauth/token, body里的参数为:

grant_type:client_credentials
client_id:client-app
client_secret:asdfholu12josadf#


以上就是搭建统一鉴权的所有流程,4种模式都可以使用,可根据不同的场景进行甄选。 

参考:

11.授权认证Oauth2_C--G的博客-CSDN博客

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

闽ICP备14008679号