1、简介
OAuth2共有5种模式,分别为:
- 授权码模式
- 隐藏模式
- 客户端模式
- 密码模式
- 刷新token模式
这里实现了比较简单的密码模式。
2、密码模式颁发access_token实现
2.1、maven工程结构如下:
添加pom依赖如下
<dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- OAuth2 -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2.2、配置文件application.properties内容如下:
server.port=9999
spring.profiles.active=simple
2.3、认证服务器AuthorizationServer配置
@Profile("simple")
@Configuration
@EnableAuthorizationServer //认证服务器注解
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager; //密码模式必须要注入authenticationManager,否则会报找不到authenticationManager错误
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception{
security.allowFormAuthenticationForClients();
super.configure(security); //如果没有支持allowFormAuthenticationForClients或者有支持但是url中没有client_id和client_secret的,走basic认证保护。导致在浏览器中输入获取access_token时,会弹出窗口要求认证。
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
clients.inMemory()
.withClient("client") //客户端名称
.secret(passwordEncoder.encode("client")) //客户端密码
.authorizedGrantTypes("password","refresh_token") //密码模式
.scopes("select") //授权范围
.resourceIds(ResourceServerConfig.RESOURCE_ID) //资源服务器的id,这个在资源服务器里有配置。
.accessTokenValiditySeconds(1200) //有效时间
.refreshTokenValiditySeconds(50000); //refresh_token的有效时间
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception{
endpoints
.authenticationManager(authenticationManager); //配置注入的authenticationManager
super.configure(endpoints);
}
}
2.4、资源服务器ResourceServer配置
@Profile("simple")
@Configuration
@EnableResourceServer //资源服务器注解
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "authorizationserver"; //就是AuthorizationServerConfigurerAdapter中配置的那个,用来标识资源服务器
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception{
super.configure(resources);
resources.resourceId(RESOURCE_ID); //配置资源服务器的id
}
@Override
public void configure(HttpSecurity http) throws Exception{
System.out.println("ResourceServerConfig中配置HttpSecurity对象执行");
http.requestMatchers().antMatchers("/me") //配置"/me"是受保护的资源。要区分开springsecurity保护的端点和ResourceServer保护的端点。
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
2.5、配置WebSecurity
@Profile("simple")
@Configuration
@EnableWebSecurity(debug = true) //可以不开启
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired //注册用户,放到内存中
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("user")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN");
}
@Override //配置不拦截"/oauth/**",否则在申请access_token会要求先认证
protected void configure(HttpSecurity http) throws Exception{
System.out.println("SecurityConfiguration中配置的对象执行");
http
.requestMatchers().anyRequest()
.and()
.authorizeRequests()
.antMatchers("/oauth/**").permitAll();
}
@Override
public void configure(WebSecurity web) throws Exception{
super.configure(web);
web.ignoring().antMatchers("favicon.ico");
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean //认证服务器中注入的authenticationManager就是从这里来的
@Override public AuthenticationManager authenticationManager() throws Exception{
return super.authenticationManager();
}
}
2.6、配置普通受springSecuity保护的端点
@Profile("simple")
@RestController
public class MainController {
@GetMapping("/")
public String email(){
return "这里是主页";
}
@GetMapping("/admin")
public String admin(){
return "这里是admin";
}
@GetMapping("/user")
public String user(){
return "这里是admin";
}
}
2.7、配置受ResourceServer保护的端点
@Profile("simple")
@RestController
public class ResourceController {
@RequestMapping("/me")
public Principal me(Principal principal){
System.out.println(principal.toString());
return principal;
}
}
2.8、main函数
@Profile("simple")
@SpringBootApplication
public class AuthSimpleApplication {
public static void main(String[] args) {
SpringApplication.run(AuthSimpleApplication.class, args);
}
}
3、测试
3.1、测试获取access_token
在postman中输入以下链接:
http://localhost:9999/oauth/token?username=user&password=user&grant_type=password&scope=select&client_id=client&client_secret=client
返回以下内容:
3.2、测试获取资源服务器保护的内容:
3.3、测试普通端点
参考文章:
[阮一峰](http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。