阅读完需:约 2 分钟
客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。
它的步骤如下:
(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。
(B)认证服务器确认无误后,向客户端提供访问令牌。
客户端模式适用于没有前端页面的应用,所以我这里用一个单元测试来个大家演示!
注意,接下来的代码是在上篇文章授权码模式的基础上改造。
首先修改 auth-server ,使之支持客户端模式:
//客户端详细信息服务配置
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()//在内存中
//用户
.withClient("xjh")
//密码
.secret(passwordEncoder.encode("123"))
//资源编号
.resourceIds("res1")
//授权的赠款类型 authorization_code 授权码模式,refresh_token 刷新Token , implicit 简化模式 , password 密码模式
.authorizedGrantTypes("authorization_code","refresh_token","implicit","password","client_credentials")
//范围
.scopes("all")
//自动批准
// .autoApprove(true)
//重定向Uris
.redirectUris("http://localhost:8082/implicit.html","http://localhost:8082/password.html");
}
这里其他地方都不变,主要是在 authorizedGrantTypes 中增加了 client_credentials 模式。
配置完成后,重启 auth-server。
接下来,在 client-app 中,通过单元测试,我们来写一段测试代码:
@SpringBootTest
class ClientAppApplicationTests {
@Autowired
RestTemplate restTemplate;
@Test
void contextLoads() {
MultiValueMap<String,String> map=new LinkedMultiValueMap();
map.add("client_id","xjh");
map.add("client_secret","123");
map.add("grant_type","client_credentials");
Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);
System.out.println("resp="+resp);
HttpHeaders headers=new HttpHeaders();
headers.add("Authorization","Bearer"+resp.get("access_token"));
HttpEntity<?> httpEntity=new HttpEntity<>(headers);
ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/hello", HttpMethod.GET, httpEntity, String.class);
System.out.println("entity.getBody() = "+entity.getBody());
}
}
这段代码跟前面的都差不多,就是请求参数不一样而已,参数 grant_type 的值为 client_credentials。其他都一样,我就不再赘述了。
测试
