Secured Page
Welcome, Name
Your authorities are authorities
```
**演示单点登录**
好,客户端程序搭建好之后,我们先来测试一下单点登录的功能。启动客户端项目,打开浏览器访问:
```
http://localhost:8082/ui/securedPage
```
可以看到,页面自动转到了授权服务器(8080 端口)的登录页面:
![](http://szv5.cn/zb_users/upload/2021/06/202106081438068774893.png)
登录后显示了当前用户名和权限:
![](http://szv5.cn/zb_users/upload/2021/06/202106081438293708419.png)
我们再启动另一个客户端网站,端口改为 8083,然后访问同样的地址:
![](http://szv5.cn/zb_users/upload/2021/06/202106081438524375661.png)\
可以看到直接是登录状态,单点登录测试成功。是不是很方便?其实,为了达成单点登录的效果,程序在背后自动实现了多次 302 重定向,整个流程为:
```
http://localhost:8083/ui/securedPage ->
http://localhost:8083/ui/login ->
http://localhost:8080/oauth/authorize?client_id=userservice3&redirect_uri=http://localhost:8083/ui/login&response_type=code&scope=FOO&state=Sobjqe ->
http://localhost:8083/ui/login?code=CDdvHa&state=Sobjqe ->
http://localhost:8083/ui/securedPage
```
**演示客户端请求资源服务器资源**
还记得吗,在上一节“搭建客户端程序”中,我们还定义了一个 remoteCall 接口,直接使用 OAuth2RestTemplate 来访问远程资源服务器的资源。现在,我们来测试一下这个接口是否可以实现自动的 OAuth 流程。访问:
```
http://localhost:8082/ui/remoteCall
```
会先转到授权服务器登录,登录后自动跳转回来:
![](http://szv5.cn/zb_users/upload/2021/06/202106081440027270008.png)
可以看到输出了用户名,对应的资源服务器服务端接口是:
```java
@PreAuthorize("hasAuthority('READ') or hasAuthority('WRITE')")
@GetMapping("name")
public String name(OAuth2Authentication authentication) {
return authentication.getName();
}
```
换一个 writer 用户登录试试,也能得到正确的输出:
![](http://szv5.cn/zb_users/upload/2021/06/202106081440577593561.png)
**总结**
今天这一讲,我们完整演示了如何使用 Spring Cloud 的 OAuth 2.0 组件基于三个程序角色(授权服务器、受保护资源服务器和客户端)实现三种 OAuth 2.0 的授权许可类型(资源拥有者凭据许可、客户端凭据许可和授权码许可)。
我们先演示了三种授权许可类型的手动流程,然后也演示了如何实现权限控制和单点登录,以及如何使用客户端程序来实现自动的 OAuth 2.0 流程。
我把今天用到的所有代码都放到了 [GitHub](https://github.com/JosephZhu1983/SpringSecurity101 "GitHub") 上,你可以点击这个链接查看。
最后,我再提一下,将来 Spring 对于 OAuth 2.0 的支持可能会转移到[由社区推进的 Spring Authorization Server 项目](https://spring.io/blog/2020/04/15/announcing-the-spring-authorization-server "由社区推进的 Spring Authorization Server 项目")上来继续运作。如果你感兴趣的话,可以及时关注这个项目的进展。