1 security认证
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 默认用户名
user - 密码
启动spring-boot服务时自动生成,如:
d9280802-b5de-4cdc-a036-f74211cd063d - 登录
http://localhost:8090/login
{
"username":"user",
"password":"d9280802-b5de-4cdc-a036-f74211cd063d"
}
2 token认证
2.1 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
2.2 配置文件
- 启动配置application-dev.yml
配置连接Redis,参数如下表。
序号 | 参数 | 描述 |
---|
1 | database | Redis数据库编号 |
2 | host | 主机IP |
3 | port | Redis连接端口 |
4 | password | Redis登录密码 |
5 | max-active | 连接池数据库最大连接数,0表示无限制 |
6 | max-idle | 连接池中最大空闲数 |
7 | max-wait | 建立连接的超时时间 |
8 | min-idle | 连接池中最小的空闲连接 |
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
password: china@asia
jedis:
pool:
max-active: 8
max-idle: 8
max-wait: -1ms
min-idle: 0
- 角色用户及接口配置
按照角色设置端口访问权限,如admin角色访问admin/**的端口。
package com.sb.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception{
resources.resourceId("rid").stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated();
}
}
- token认证配置AuthorizationServerConfig.java
生成Token时使用withClient值生辰请求Token的Authorization字段值。
序号 | 参数 | 描述 |
---|
1 | withClient(“client”) | 用户名,client,用于生成base64编码 |
2 | accessTokenValiditySeconds(1800) | token有效时间,单位:秒 |
3 | secret(new BCryptPasswordEncoder().encode(“123456”) | 密码模式,密码为123456 |
package com.sb.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.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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.store.redis.RedisTokenStore;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Autowired
UserDetailsService userDetailsService;
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
clients.inMemory()
.withClient("client")
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(1800)
.resourceIds("rid")
.scopes("all")
.secret(new BCryptPasswordEncoder().encode("123456"));
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception{
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception{
security.allowFormAuthenticationForClients();
}
}
- 用户认证配置WebSecurityConfig.java
指定用户生成特定的Token,这个Token用于该用户角色访问特定资源。
序号 | 参数 | 描述 |
---|
1 | withUser(“admin”) | 用户名,admin,用于请求token |
2 | password(new BCryptPasswordEncoder().encode(“123456”)) | 用户密码,用于请求token |
3 | secret(new BCryptPasswordEncoder().encode(“123456”) | 密码模式,密码为123456 |
package com.sb.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
@Bean
@Override
protected UserDetailsService userDetailsService(){
return super.userDetailsService();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication()
.withUser("admin")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("admin")
.and()
.withUser("xiao")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http.antMatcher("/oauth/**")
.authorizeRequests()
.antMatchers("/oauth/**")
.permitAll()
.and()
.csrf()
.disable();
}
}
2.3 获取Token
curl -X POST \
'http://localhost:8090/oauth/token?grant_type=password&username=xiao&password=123456' \
-H 'Accept: application/json' \
-H 'Authorization: Basic Y2xpZW50OjEyMzQ1Ng==' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 9d89cd2b-5bb1-41ad-838e-91f8aef1266e'
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://localhost:8090/oauth/token?grant_type=password&username=xiao&password=123456")
.post(null)
.addHeader("Authorization", "Basic Y2xpZW50OjEyMzQ1Ng==")
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("Cache-Control", "no-cache")
.addHeader("Postman-Token", "ea2669a8-b183-4aa4-91b9-ba2160a16dd1")
.build();
Response response = client.newCall(request).execute();
序号 | 参数 | 描述 |
---|
1 | Authorization | 认证字段,格式为Basic base64编码,其中Basic为一个空格,base64编码为token配置中的用户和密码的base64编码,格式为:username:password如client:123456 |
2 | Accept | 接受数据格式 |
3 | Content-Type | 数据内容类型 |
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fd2b3bb58a70f047bbef30ec69d38f02.png#pic_center)
图2.1 请求样例
{
"access_token": "d9c0dd23-76d9-4b04-a732-bf62556d3979",
"token_type": "bearer",
"refresh_token": "a3ccc65e-b117-4c96-8d7a-bce2cc180cee",
"expires_in": 1799,
"scope": "all"
}
2.4 刷新Token
curl -X POST \
'http://localhost:8090/oauth/token?grant_type=refresh_token&refresh_token=895f5c39-4922-44f9-ab58-8cb6ac5c68e5' \
-H 'Authorization: Basic Y2xpZW50OjEyMzQ1Ng==' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-H 'Postman-Token: cf384165-cec7-4368-8980-1b3d6cc3bb8e'
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3da4c55568a1df56f69356804612050a.png#pic_center)
图2.2 刷新Token
{
"access_token": "50728d50-672b-49df-81d4-114e4789389f",
"token_type": "bearer",
"refresh_token": "895f5c39-4922-44f9-ab58-8cb6ac5c68e5",
"expires_in": 1799,
"scope": "all"
}
2.5 添加Token请求接口
接口URL中添加access_token=获取token时生成的access_token
curl -X GET \
'http://localhost:8090/api/get-infos/all?access_token=d9c0dd23-76d9-4b04-a732-bf62556d3979' \
-H 'Cache-Control: no-cache' \
-H 'Postman-Token: 03666668-55cc-4c32-9cd7-cca3d1672255'
http://localhost:8090/api/get-infos/all?access_token=d9c0dd23-76d9-4b04-a732-bf62556d3979
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f9e50944d8d7b339a2c5ab92f73f779a.png#pic_center)
图2.3 添加Token请求接口
3 小结
Token生成流程如图3.1。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/db0ff3e687bcd974b14186749c160466.png#pic_center)
图3.1 OAuth2 Token生成流程
【参考文献】
[1]https://blog.csdn.net/qq_37139980/article/details/90605708
[2]https://blog.csdn.net/u012613251/article/details/81279060
[3]https://www.cnblogs.com/rwxwsblog/p/5846752.html