OAuth2简介
OAuth2是一个基于令牌的安全验证和授权框架,主要分为四个部分
1)资源所有者
定义哪些应用程序可以调用其服务,哪些用户可以访问该服务,以及他们可以使用该服务完成哪些事情。(应用与用户都可以是资源所有者)
2)受保护的资源
这是开发人员想要保护的资源,只有通过授权的用户才能够访问,比如商品服务、库存服务, 资源所有者从资源服务器获取的资源
3)应用程序
代表用户调用服务的应用程序,也就是client端。
4)OAuth2验证服务器 EnableAuthorizationServer
验证服务器是应用程序介于应用程序于访问的服务的中介,Oauth2验证服务允许用户对自己进行验证,而不必将用户凭证传递到调用的每个服务。可以理解为用户在访问一个商品服务之前,通过Oauth2进行验证,然后得到token,通过token从Oauth2资源服务器获取到登陆信息将有限的信息传递下去,不必将用户名密码之类的信息传递下去
图片来源https://deepzz.com/post/what-is-oauth2-protocol.html
OAuth2 授权模式
- 密码模式 password
- 客户端凭据 client credential
- 授权码 authorization code
- 隐式 implicit
密码模式 password
密码模式一般用于都是可信的的情况,也就是说资源所有者,资源服务器,授权服务都是一家的
- 创建一个oauth2验证服务
pom依赖
<!--spring boot 版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
.....
<!--作为资源服务获取用户信息需要的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--作为验证服务包含了security 和 oauth2-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
AuthServerApplication .java
@SpringBootApplication
@RestController
@EnableAuthorizationServer // 告诉springcloud该服务是oauth2鉴权服务
@EnableResourceServer // 告诉springcloud该服务是oauth2也是资源服务,为了保护该类内的/user接口
public class AuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServerApplication.class, args);
}
@RequestMapping(value = {"/user"}, produces = "application/json")
public Map<String, Object> user(OAuth2Authentication user) {
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
return userInfo;
}
}
OAuth2Config
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 定义哪些客户端可以注册到了服务
clients.inMemory()
.withClient("clientId")
.secret("{noop}clientSecret")
// 支持的授权模式 密码模式和客户端凭证
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
// 定义访问作用域,也就是当用户使用某一个scope授权之后,可以根据不同的scope封装不同的user信息,比如webclient会封装角色,mobileclient封装角色和资源api,由开发人员定义即可
.scopes("webclient", "mobileclient");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 使用默认的验证管理器和用户信息服务
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
WebSecurityConfig
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("{noop}password1")
.roles("USER")
.and()
.withUser("admin")
.password("{noop}password2")
.roles("USER", "ADMIN");
}
}
- 测试授权接口
使用postman测试
url: http://localhost:port/oauth/token
1.使用authentication的方式
2.使用 Header的方式
Authentication: Basic base64(clientId:clientSecret)
header.png
以上二选一
** form表单参数,密码授权模式 **
参数2.png
响应结果
{
"access_token": "0b9bb396-e7fb-43f1-a580-50ea28ff90dc",
"token_type": "bearer",
"refresh_token": "efdbc090-ced6-4e07-a0f9-fdbd5241ba0e",
"expires_in": 42723,
"scope": "webclient"
}
最基本的oauth2服务搭建完毕
客户端凭据 client credential
一般是用于没有用户的客户端进行授权的方式,通过clientId clientSecret进行授权
授权码 authorization code
授权码模式一般用于,提供第三方授权的情况,比如微信提供的第三方登陆等,再比如leecode提供github登陆这种情况,
也就是说微信提供了一个统一第三方登陆平台,所有需要的接入方,注册到了微信就能够通过授权码授权
隐式 implicit
没有刷新token
待续具体的使用场景
网友评论