一. 引入依赖
<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.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
二. 授权服务器配置
@Configuration
@EnableAuthorizationServer //授权服务器
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Autowired
AuthenticationManager authenticationManager;
@Autowired
UserDetailsService userDetailsService;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 用来配置客户端的详细信息
* 授权服务器要做两方面的检验,一方面是校验客户端,另一方面则是校验用户,
* 这里就是配置校验客户端。客户端的信息我们可以存在数据库中,
* 这其实也是比较容易的,和用户信息存到数据库中类似,但是这里为了简化代码,我还是将客户端信息存在内存中,
* 这里我们分别配置了客户端的 id,secret、资源 id、授权类型、授权范围。授权类型一共有四种,
* 四种之中不包含 refresh_token 这种类型,但是在实际操作中,refresh_token 也被算作一种
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientId")
.secret(passwordEncoder().encode("123"))
.resourceIds("res")
.authorizedGrantTypes("refresh_token", "password")
.scopes("all")
.accessTokenValiditySeconds(3600)
.autoApprove(true);
}
/**
* 用来配置令牌的访问端点和令牌服务
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
/**
* 支持clientId和client_secret做登录认证
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
}
三. 资源服务器配置
@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
/**
* 表示资源是基于token来认证的
*
* @param resources
* @throws Exception
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("res").stateless(true);
}
/**
* 配置所访问相应资源时需要相应的角色
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated();
}
}
四. 用户security配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
protected UserDetailsService userDetailsService() {
return super.userDetailsService();
}
@Autowired
PasswordEncoder passwordEncoder;
/**
* 配置登录用户
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("zhangsan").password(passwordEncoder.encode("123")).roles("admin")
.and()
.withUser("lisi").password(passwordEncoder.encode("123")).roles("user");
}
/**
* 配置security放行路径(这里因为要通过oauth相关接口申请令牌 要放行)
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth/**")
.authorizeRequests()
.antMatchers("/oauth/**")
.permitAll()
.and().csrf().disable();
}
}
五. 测试
@RestController
public class TestController {
@RequestMapping("/admin")
public String admin(){
return "admin"; //需要admin角色
}
@RequestMapping("/user")
public String user(){
return "user"; //需要user角色
}
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}