目录
1、依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.11.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2、SecurityConfig核心配置
在这里插入代码片@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//使用内存方式创建用户
auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("123")).roles("ADMIN");
auth.inMemoryAuthentication().withUser("test").password(passwordEncoder.encode("123")).roles("test");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/goods/list").access("hasAnyAuthority('ROLE_ADMIN','ROLE_test')");
http.authorizeRequests().antMatchers("/goods/add").access("hasAnyAuthority('ROLE_ADMIN')");
http.authorizeRequests().antMatchers("/goods/update").access("hasAnyAuthority('ROLE_ADMIN')");
http.authorizeRequests().antMatchers("/goods/delete").access("hasAnyAuthority('ROLE_ADMIN')");
//这里要放行oauth2请求路径
http.authorizeRequests().antMatchers("/oauth/**").permitAll();
http.formLogin().and().logout().logoutSuccessUrl("/logout");
}
@Override
public void configure(WebSecurity web) throws Exception {
}
}
3、 Oauth2认证服务器配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final String RESOURCE_ID = "my-resource";
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Autowired
AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//基于内存
clients.inMemory()
//client1允许client_credentials认证
.withClient("client1")
.secret(passwordEncoder.encode("client1_secret"))
.resourceIds(ResourceServerConfig.RESOURCE_ID)
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("access_token")
.authorities("client")
.and()
//client2允许密码认证
.withClient("client2")
.secret(passwordEncoder.encode("client2_secret"))
.resourceIds(ResourceServerConfig.RESOURCE_ID)
.authorizedGrantTypes("password", "refresh_token")
.scopes("access_token")
.authorities("client");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持OAUTH相关接口以GET和POST方法请求
}
/**
* 支持请求的时候,已表单的形式发送数据
* @param oauthServer
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
}
}
4、 Oauth2资源服务器配置
/**
* @author zhe.xiao
* @date 2021-03-26 15:35
* @description
* Oauth2 第二步 配置资源服务器
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "my-resource";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID).stateless(true);
}
}
5、编写Controller接口测试
@RestController
@RequestMapping("/goods")
public class GoodsController {
@GetMapping("/list")
public String list(){
return "商品列表";
}
@GetMapping("/add")
public String add(){
return "添加商品成功";
}
@GetMapping("/update")
public String update(){
return "修改商品成功";
}
@GetMapping("/delete")
public String delete(){
return "删除商品成功";
}
}
6、测试结果:
6.1、client_credentials认证:
请求路径: http://localhost:9101/oauth/token
参数:
grant_type :client_credentials
scope :access_token
client_id :client1
client_secret :client1_secret
6.2 密码认证:
请求路径: http://localhost:9101/oauth/token
参数:
grant_type :password
scope :access_token
client_id :client2
client_secret :client2_secret
username :admin
password:123
因为我们上面tokenStore指明的这些数据存在Redis里面,所以可以发现在生成token后redis自动新增了许多key
6.3 检查token是否合法
请求路径:http://localhost:9101/oauth/check_token?token=81bf3d0f-fce0-4c97-9ea7-a2a859869d7d