
授权码模式(authorization code):正宗的OAuth2的授权模式,客户端先将用户导向认证服务器,登录后获取授权码,然后进行授权,最后根据授权码获取访问令牌; 简化模式(implicit):和授权码模式相比,取消了获取授权码的过程,直接获取访问令牌; 密码模式(resource owner password credentials):客户端直接向用户获取用户名和密码,之后向认证服务器获取访问令牌; 客户端模式(client credentials):客户端直接通过客户端认证(比如client_id和client_secret)从认证服务器获取访问令牌。
这里我们用的是密码模式
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>bi-cloud</artifactId> <groupId>com.bi.cloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>oauth</artifactId> <dependencies> <!--集成公共模块--> <dependency> <groupId>com.bi.cloud</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--nacos service discovery client依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--nacos config client 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- Java Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--导入spring cloud oauth2依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies></project>package com.bi.cloud;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.domain.EntityScan;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClient@EntityScan("com.bi.cloud.pojo")@MapperScan("com.bi.cloud.dao")public class OauthApplication { public static void main(String[] args) { SpringApplication.run(OauthApplication.class, args); }}spring: profiles: active: test---server: port: 8002spring: profiles: test application: name: bi-cloud-oauth cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认properties---server: port: 8002spring: profiles: pre application: name: bi-cloud-oauth cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认properties---server: port: 8002spring: profiles: prd application: name: bi-cloud-oauth cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认propertiesspring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.*.***:3306/****?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true username: ***** password: admin druid: initialSize: 10 minIdle: 10 maxActive: 30 maxWait: 50000 redis: database: 1 host: 192.168.*.*** port: 6379 password: **** timeout: 5000mybatis: mapper-locations: classpath:mapper/*.xml**分别添加 RedisTokenStoreConfig.class 、OAuthConfig.class
、WebSecurityConfig.class**
package com.bi.cloud.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.TokenStore;import javax.sql.DataSource;@Configuration@EnableAuthorizationServerpublic class OAuthConfig extends AuthorizationServerConfigurerAdapter { @Autowired public PasswordEncoder passwordEncoder; @Autowired public UserDetailsService kiteUserDetailsService; @Autowired private AuthenticationManager authenticationManager; @Autowired private TokenStore redisTokenStore; @Autowired private DataSource dataSource; @Override public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception { /** * redis token 方式
*/
endpoints.authenticationManager(authenticationManager)
.userDetailsService(kiteUserDetailsService)
.tokenStore(redisTokenStore); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { JdbcClientDetailsServiceBuilder jcsb = clients.jdbc(dataSource); jcsb.passwordEncoder(passwordEncoder); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients(); security.checkTokenAccess("isAuthenticated()"); security.tokenKeyAccess("isAuthenticated()"); }}package com.bi.cloud.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.security.oauth2.provider.token.TokenStore;import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;@Configurationpublic class RedisTokenStoreConfig { @Autowired private RedisConnectionFactory redisConnectionFactory; @Bean public TokenStore redisTokenStore (){ return new RedisTokenStore(redisConnectionFactory); }}package com.bi.cloud.config;import org.springframework.context.annotation.Bean;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 允许匿名访问所有接口 主要是 oauth 接口
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").permitAll();
}
}//oauth_client表create table oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256));INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove)VALUES ('user-client', '$2a$10$o2l5kA7z.Caekp72h5kU7uqdTDrlamLq.57M1F6ulJln9tRtOJufq', 'all', 'authorization_code,refresh_token,password', null, null, 3600, 36000, null, true);INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove)VALUES ('order-client', '$2a$10$GoIOhjqFKVyrabUNcie8d.ADX.qZSxpYbO6YK4L2gsNzlCIxEUDlW', 'all', 'authorization_code,refresh_token,password', null, null, 3600, 36000, null, true);//-------------------------------------------------------------------------------------------------------//用户表CREATE TABLE `bi_user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;INSERT INTO `bi_user`(`id`, `username`, `password`) VALUES (1, 'admin', '123456');//正常数据库密码加密,这里只为演示package com.bi.cloud.service;import com.bi.cloud.dao.UserDao;import com.bi.cloud.pojo.Users;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.stereotype.Component;import java.util.ArrayList;@Slf4j@Componentpublic class AuthUserService implements UserDetailsService { @Autowired private UserDao userDao; @Autowired private PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { log.info("username:" + username); // 查询数据库操作 Users users = userDao.getUsers(username); if (StringUtils.isBlank(users.getPassword())) { throw new UsernameNotFoundException("the user is not found"); } String password = passwordEncoder.encode(users.getPassword()); return new User(username, password, new ArrayList<>()); }}engine 子模块
gateway内容迁移至api
bootstrap.yml配置
spring: profiles: active: test---server: port: 8008spring: profiles: test cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 config: server-addr: 127.0.0.1:8848 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认properties sentinel: transport: dashboard: 127.0.0.1:8080 #配置Sentinel dashboard地址 port: 8719 #这个端口配置会在应用对应的机器上启动一个Http Server,该Server会与 Sentinel 控制台做交互 datasource: flow: nacos: server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置 dataId: cloud-sentinel-flow-service #nacos中存储规则的dataId groupId: DEFAULT_GROUP #nacos中存储规则的groupId namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID data-type: json #配置文件类型 rule-type: flow #类型来自RuleType类 - 流控规则 degrade: nacos: server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置 dataId: cloud-sentinel-degrade-service #nacos中存储规则的dataId groupId: DEFAULT_GROUP #nacos中存储规则的groupId namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID data-type: json #配置文件类型 rule-type: degrade #类型来自RuleType类 - 熔断规则 gateway: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务] routes: - id: bi-cloud-oauth # 当前路由的标识, 要求唯一
uri: lb://bi-cloud-oauth # lb指的是从 nacos 中按照名称获取微服务,并遵循负载均衡策略
predicates: # 断言(就是路由转发要满足的条件)
- Path=/oauth/** # 当请求路径满足Path指定的规则时,才进行路由转发
# 我们⾃定义的路由 ID,保持唯⼀
- id: bi-cloud-api
# ⽬标服务地址(部署多实例)
uri: lb://bi-cloud-api
# gateway⽹关从服务注册中⼼获取实例信息然后负载后路由
# 断⾔:路由条件,Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默认⽅法来将 Predicate 组合成其他复杂的逻辑(⽐如:与,或,⾮)。
predicates:
- Path=/bi-gateway/api/**
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
- StripPrefix=1 # 转发之前去掉1层路径
application:
name: bi-cloud-gateway
---
server:
port: 8008
spring:
profiles: pre
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123
config:
server-addr: 127.0.0.1:8848
namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
file-extension: yml #默认properties
sentinel:
transport:
dashboard: 127.0.0.1:8080 #配置Sentinel dashboard地址
port: 8719 #这个端口配置会在应用对应的机器上启动一个Http Server,该Server会与 Sentinel 控制台做交互
datasource:
flow:
nacos:
server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置
dataId: cloud-sentinel-flow-service #nacos中存储规则的dataId
groupId: DEFAULT_GROUP #nacos中存储规则的groupId
namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID
data-type: json #配置文件类型
rule-type: flow #类型来自RuleType类 - 流控规则
degrade:
nacos:
server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置
dataId: cloud-sentinel-degrade-service #nacos中存储规则的dataId
groupId: DEFAULT_GROUP #nacos中存储规则的groupId
namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID
data-type: json #配置文件类型
rule-type: degrade #类型来自RuleType类 - 熔断规则
gateway:
# 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
routes:
- id: bi-cloud-oauth # 当前路由的标识, 要求唯一
uri: lb://bi-cloud-oauth # lb指的是从 nacos 中按照名称获取微服务,并遵循负载均衡策略
predicates: # 断言(就是路由转发要满足的条件)
- Path=/oauth/** # 当请求路径满足Path指定的规则时,才进行路由转发
# 我们⾃定义的路由 ID,保持唯⼀
- id: bi-cloud-api
# ⽬标服务地址(部署多实例)
uri: lb://bi-cloud-api
# gateway⽹关从服务注册中⼼获取实例信息然后负载后路由
# 断⾔:路由条件,Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默认⽅法来将 Predicate 组合成其他复杂的逻辑(⽐如:与,或,⾮)。
predicates:
- Path=/bi-gateway/api/**
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
- StripPrefix=1 # 转发之前去掉1层路径
application:
name: bi-cloud-gateway
---
server:
port: 8008
spring:
profiles: prd
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212
config:
server-addr: 127.0.0.1:8848
namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
file-extension: yml #默认properties
sentinel:
transport:
dashboard: 127.0.0.1:8080 #配置Sentinel dashboard地址
port: 8719 #这个端口配置会在应用对应的机器上启动一个Http Server,该Server会与 Sentinel 控制台做交互
datasource:
flow:
nacos:
server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置
dataId: cloud-sentinel-flow-service #nacos中存储规则的dataId
groupId: DEFAULT_GROUP #nacos中存储规则的groupId
namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID
data-type: json #配置文件类型
rule-type: flow #类型来自RuleType类 - 流控规则
degrade:
nacos:
server-addr: 127.0.0.1:8848 #nacos的访问地址,,根据上面准备工作中启动的实例配置
dataId: cloud-sentinel-degrade-service #nacos中存储规则的dataId
groupId: DEFAULT_GROUP #nacos中存储规则的groupId
namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间的ID
data-type: json #配置文件类型
rule-type: degrade #类型来自RuleType类 - 熔断规则
gateway:
# 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
routes:
- id: bi-cloud-oauth # 当前路由的标识, 要求唯一
uri: lb://bi-cloud-oauth # lb指的是从 nacos 中按照名称获取微服务,并遵循负载均衡策略
predicates: # 断言(就是路由转发要满足的条件)
- Path=/oauth/** # 当请求路径满足Path指定的规则时,才进行路由转发
# 我们⾃定义的路由 ID,保持唯⼀
- id: bi-cloud-api
# ⽬标服务地址(部署多实例)
uri: lb://bi-cloud-api
# gateway⽹关从服务注册中⼼获取实例信息然后负载后路由
# 断⾔:路由条件,Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默认⽅法来将 Predicate 组合成其他复杂的逻辑(⽐如:与,或,⾮)。
predicates:
- Path=/bi-gateway/api/**
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
- StripPrefix=1 # 转发之前去掉1层路径
application:
name: bi-cloud-gatewaypom.xml修改
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>gateway</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> <!--GateWay 网关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--引入webflux--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!--日志依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <!--测试依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok工具--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency> <!-- Actuator可以帮助你监控和管理Spring Boot应⽤--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--nacos config client 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--链路追踪--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> </dependencies> <dependencyManagement> <!--spring cloud依赖版本管理--> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--SCA --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--SCA --> </dependencies> </dependencyManagement> <build> <plugins> <!--编译插件--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> <encoding>utf-8</encoding> </configuration> </plugin> <!--打包插件--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>Nacos配置修改删除即可
GatewayApplication.class 启动类
package com.bi.cloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClientpublic class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); }}pom.xml 展示
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>bi-cloud</artifactId> <groupId>com.bi.cloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>common</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- StringUtils --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.11</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.22</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build></project>新增或修改 UserDao、Users、UserService、UserMapper.xml 文件
package com.bi.cloud.dao;import com.bi.cloud.pojo.Users;import org.apache.ibatis.annotations.Mapper;@Mapperpublic interface UserDao { Users getUsers(String username);}package com.bi.cloud.pojo;import lombok.Data;import java.io.Serializable;@Datapublic class Users implements Serializable { private long id; private String username; private String password;}package com.bi.cloud.service;import com.bi.cloud.pojo.Users;public interface UserService { Users userInfo(String username);}<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.bi.cloud.dao.UserDao"> <resultMap id="BaseResultMap" type="com.bi.cloud.pojo.Users"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> </resultMap> <sql id="Base_Column_List"> id, username, password </sql> <select id="getUsers" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from bi_user where username = #{username} </select></mapper>为RocketMQ消息监听,我们现在用不到,所以在这里把项目中的RocketMQ Jar包、方法都已经注视掉了)
pom.xml修改
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>bi-cloud</artifactId> <groupId>com.bi.cloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>engine</artifactId> <dependencies> <!--集成公共模块--> <dependency> <groupId>com.bi.cloud</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--nacos service discovery client依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--nacos config client 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--spring cloud+dubbo 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-apache-dubbo-adapter</artifactId> </dependency> <!--rocketmq--> <!--<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>--> </dependencies></project>UserServiceImpl.class 修改
package com.bi.cloud.service.Impl;import com.bi.cloud.dao.UserDao;import com.bi.cloud.pojo.Users;import com.bi.cloud.service.UserService;import org.apache.dubbo.config.annotation.Service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Service@Componentpublic class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public Users userInfo(String username) { return userDao.getUsers(username); }}bootstrap.yml 配置文件
spring: profiles: active: test #默认运行环境---server: port: 8001spring: profiles: test #运行环境 + 命名空间名称 application: name: bi-cloud-engine #唯一名称 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认propertiesmybatis: mapper-locations: classpath:mapper/*.xml---server: port: 8001spring: profiles: pre #运行环境 + 命名空间名称 application: name: bi-cloud-engine #唯一名称 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认propertiesmybatis: mapper-locations: classpath:mapper/*.xml---server: port: 8001spring: profiles: prd #运行环境 + 命名空间名称 application: name: bi-cloud-engine #唯一名称 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认propertiesmybatis: mapper-locations: classpath:mapper/*.xmlNacos配置
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.*.***:3306/*****?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true username: **** password: **** druid: initialSize: 10 minIdle: 10 maxActive: 30 maxWait: 50000dubbo: scan: # dubbo 服务扫描基准包 base-packages: com.bi.cloud.service protocol: # dubbo 协议 name: dubbo # dubbo 协议端口( -1 表示自增端口,从 20880 开始) port: -1 host: 127.0.0.1 registry: # 挂载到 Spring Cloud 的注册中心 address: spring-cloud://localhostrocketmq: name-server: 192.168.1.***:9876 producer: # 小坑:必须指定group group: test-groupEngineApplication.class 启动类
package com.bi.cloud;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.domain.EntityScan;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClient@EntityScan("com.bi.cloud.pojo")@MapperScan("com.bi.cloud.dao")public class EngineApplication { public static void main(String[] args) { SpringApplication.run(EngineApplication.class, args); }}RocketMQ,这里已经注释掉,不需要)
ResourceServerConfig.class
package com.bi.cloud.config;import com.bi.cloud.handler.AuthExceptionEntryPoint;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.RemoteTokenServices;import org.springframework.security.oauth2.provider.token.TokenStore;import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;@Configuration@EnableResourceServer@EnableGlobalMethodSecurity(prePostEnabled = true)public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Value("${security.oauth2.client.client-id}") private String clientId; @Value("${security.oauth2.client.client-secret}") private String secret; @Value("${security.oauth2.authorization.check-token-access}") private String checkTokenEndpointUrl; @Autowired private RedisConnectionFactory redisConnectionFactory; @Autowired private AuthExceptionEntryPoint authExceptionEntryPoint; @Bean public TokenStore redisTokenStore() { return new RedisTokenStore(redisConnectionFactory); } @Bean public RemoteTokenServices tokenService() { RemoteTokenServices tokenService = new RemoteTokenServices(); tokenService.setClientId(clientId); tokenService.setClientSecret(secret); tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl); return tokenService; } @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.authenticationEntryPoint(authExceptionEntryPoint); }}UserBlockHandler.class
package com.bi.cloud.config;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;import com.alibaba.csp.sentinel.slots.block.flow.FlowException;import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;import com.alibaba.csp.sentinel.slots.system.SystemBlockException;import com.alibaba.fastjson.JSON;import java.util.HashMap;public class UserBlockHandler { public static String handleException(BlockException ex) { HashMap<String, Object> map = new HashMap<>(); if (ex instanceof FlowException) { map.put("code", -1); map.put("msg", "系统限流,请稍等"); } else if (ex instanceof DegradeException) { map.put("code", -2); map.put("msg", "降级了"); } else if (ex instanceof ParamFlowException) { map.put("code", -3); map.put("msg", "热点参数限流"); } else if (ex instanceof SystemBlockException) { map.put("code", -4); map.put("msg", "系统规则(负载/...不满足要求)"); } else if (ex instanceof AuthorityException) { map.put("code", -5); map.put("msg", "授权规则不通过"); } return JSON.toJSONString(map); } public static String handleError() { HashMap<String, Object> map = new HashMap<>(); map.put("code", 500); map.put("msg", "系统异常"); return JSON.toJSONString(map); }}UserController.class
package com.bi.cloud.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.fastjson.JSON;import com.bi.cloud.config.UserBlockHandler;import com.bi.cloud.pojo.Users;import com.bi.cloud.service.UserService;import org.apache.dubbo.config.annotation.Reference;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api/user")public class UserController { @Reference private UserService userService; /** * 获取用户信息
*/
@PostMapping("/userInfo")
public String userInfo() {
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
return JSON.toJSONString(userService.userInfo(userName));
} /** * 测试流控规则
*/
@PostMapping("/testFlow")
@SentinelResource(value = "user-testFlow",
blockHandlerClass = UserBlockHandler.class, //对应异常类
blockHandler = "handleException", //只负责sentinel控制台配置违规
fallback = "handleError", //只负责业务异常
fallbackClass = UserBlockHandler.class)
public String testFlow() {
Users user = userService.userInfo("admin");
return JSON.toJSONString(user);
} /** * 测试降级规则
*/
@PostMapping("/testDegrade")
@SentinelResource(value = "user-testDegrade",
blockHandlerClass = UserBlockHandler.class, //对应异常类
blockHandler = "handleException", //只负责sentinel控制台配置违规
fallback = "handleError", //只负责业务异常
fallbackClass = UserBlockHandler.class)
public String testDegrade() {
Users user = userService.userInfo("admin");
return JSON.toJSONString(user);
}
}AuthExceptionEntryPoint.class (oauth登录异常处理)
package com.bi.cloud.handler;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;import org.springframework.security.core.AuthenticationException;import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;import org.springframework.security.web.AuthenticationEntryPoint;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@Component@Slf4jpublic class AuthExceptionEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { Throwable cause = authException.getCause(); response.setHeader("Content-Type", "application/json;charset=UTF-8"); try { JSONObject body = new JSONObject(); body.put("code", 1001); body.put("msg", "token无效"); if (!(cause instanceof InvalidTokenException)) { body.put("code", 1002); body.put("msg", "token丢失"); } response.getWriter().write(body.toJSONString()); } catch (IOException e) { log.error("token认证失败", e); } }}ApiApplication.class 启动类
package com.bi.cloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.context.annotation.ComponentScan;@SpringBootApplication@EnableDiscoveryClientpublic class ApiApplication { public static void main(String[] args) { SpringApplication.run(ApiApplication.class, args); }}bootstrap.yml 配置
spring: profiles: active: test---server: port: 8003spring: profiles: test application: name: bi-cloud-api cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: a60273f4-07fb-4568-82eb-d078a3b02107 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认properties---server: port: 8003spring: profiles: pre application: name: bi-cloud-api cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: c60d2198-0b2f-46c1-82cb-4c2f20fb8123 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认properties---server: port: 8003spring: profiles: prd application: name: bi-cloud-api cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID config: server-addr: 127.0.0.1:8848 #Nacos 链接地址 namespace: 0be74aa4-00e5-4c48-ae8c-34965c327212 #Nacos 命名空间ID group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 file-extension: yml #默认propertiesNacos 配置
dubbo: registry: # 挂载到 Spring Cloud 注册中心 address: spring-cloud://localhost cloud: # 订阅服务提供方的应用列表,订阅多个服务提供者使用 "," 连接 subscribed-services: bi-cloud-enginerocketmq: name-server: 192.168.1.117:9876 producer: # 小坑:必须指定group group: test-groupspring: redis: database: ` host: 192.168.1.206 port: 6379 password: root timeout: 5000security: oauth2: client: client-id: user-client client-secret: user-secret-8888 user-authorization-uri: http://localhost:8002/oauth/authorize access-token-uri: http://localhost:8002/oauth/token resource: id: user-client user-info-uri: user-info authorization: check-token-access: http://localhost:8002/oauth/check_tokenpom.xml 配置
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>bi-cloud</artifactId> <groupId>com.bi.cloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>api</artifactId> <dependencies> <!--集成公共模块--> <dependency> <groupId>com.bi.cloud</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </exclusion> <exclusion> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </exclusion> <exclusion> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </exclusion> </exclusions> </dependency> <!--nacos service discovery client依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--nacos config client 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--sentinel 核心环境 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- Sentinel支持采用 Nacos 作为规则配置数据源,引入该适配依赖 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> </dependency> <!--spring cloud+dubbo 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-apache-dubbo-adapter</artifactId> </dependency> <!-- Java Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!--JSON 序列化依赖 和 模板引擎--> <!-- <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!-- rocketmq --> <!--<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>--> <!--导入spring cloud oauth2依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies></project>完整Naocs 列表展示
1. 启动项目
POST http://localhost:8002/oauth/token?grant_type=password&username=admin&password=123456&scope=allundefined Accept: /undefined Cache-Control: no-cacheundefined Authorization: Basic dXNlci1jbGllbnQ6dXNlci1zZWNyZXQtODg4OA==
运行请求后,如果参数都正确的话,获取到的返回内容如下,是一段 json 格式
{undefined "access_token": "34f979d2-525f-4138-830d-dcbd7a2a5d02",undefined "token_type": "bearer",undefined "refresh_token": "98a9153b-6a98-4182-9af3-0a1321da7c0d",undefined "expires_in": 3599,undefined "scope": "all"undefined }
**token 过期后,用 refresh_token 换取 access_token
一般都会设置 access_token 的过期时间小于 refresh_token 的过期时间,以便在 access_token
过期后,不用用户再次登录的情况下,获取新的 access_token。**
POST http://localhost:8002/oauth/token?grant_type=refresh_token&refresh_token=706dac10-d48e-4795-8379-efe8307a2282undefined Accept: /undefined Cache-Control: no-cacheundefined Authorization: Basic dXNlci1jbGllbnQ6dXNlci1zZWNyZXQtODg4OA==
POST http://localhost:8008/bi- gateway/api/user/userInfoundefined Authorization: bearer 88d08a76-f4bf-4821-93ab-10eca7bdddb6
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。