- A+
---
title: Spring Security OAuth2.0 官方例子详解
date: 2019-01-04 16:16:47
categories: Spring Security
tags:
- format
- debug
- 详解
- token
- redirect_uri
- 授权
- xml
- properties
- 官方
- security
- oauth2.0
- 例子
- 单点登录
- Sparklr
- tonr
- photos
- 相片
- authorize
- SparklrController
- RequestMapping
- sparklrService
- getSparklrPhotoIds
- SparklrServiceImpl
- getForObject
- sparklrRestTemplate
- RestTemplate
- RestOperations
- execute
- OAuth2RestTemplate
- accessToken
- 令牌
- getAccessToken
- AuthorizationCodeAccessTokenProvider
- UserRedirectRequiredException
- OAuth2ClientContextFilter
- sendRedirect
- client_id
- respondse_type
- AuthorizationEndpoint
---
这几天需要用到单点登录,准备学习下Spring Security OAuth2.0
官方例子:https://github.com/spring-projects/spring-security-oauth
按照步骤项目跑进来后没什么问题,但是动作的过程不是太清楚,于是开始读代码。但是发现看了几遍还是一脸懵。。google后发现很少有文章写这个例子的解析,有也是泛泛而谈。
对着一些网上的解析和自己debug,终于对整个过程有了一个大致的认识。
项目跑起来后,访问http://localhost:8080/tonr2即可进入tonr的登录界面,点击login后就登录进了tonr系统,这时我们点View my Sparklr photos链接时,会到sparklr的登录界面,登录后会让我们授权,然后会返回sparklr的相片详细画面。
结合代码,具体的过程是这样的。
当我们点击View my Sparklr photos链接时,链接的地址是"/sparklr/photos"。
当tonr系统接收后这个请求时,会进入到SparklrController.java的photos方法里,因为该方法匹配了@RequestMapping("/sparklr/photos"),在此方法里会调用sparklrService.getSparklrPhotoIds()函数。
getSparklrPhotoIds()方法的实现在SparklrServiceImpl.java里。tonr里最核心的代码就是此类的getSparklrPhotoIds方法。
sparklrRestTemplate.getForObject(
URI.create(sparklrPhotoListURL), byte[].class)
这里的sparklrPhotoListURL实际上就是这个地址http://localhost:8080/sparklr2/photos?format=xml。
这个地址实际上是请求sparklr系统里获取相片详细。
这个地址在哪定义的?tonr工程里的sparklr.properties文件里定义了几个需要用到的地址,除了上面这个外还包括/oauth/authorize和/oauth/token等等。
上面这行代码会调用RestTemplate类的getForObject方法。(这里需要注意:sparklrRestTemplate的类型为RestOperations,RestOperations是一个接口,而RestTemplate是RestOperations的实现类)
getForObject方法的最后会调用execute方法,execute方法实际上调用的是doExecute方法。
(这里我没有搞懂:应该执行RestTemplate里的doExecute方法才对啊,但是根据实际debug的结果,居然是进了OAuth2RestTemplate.java类的doExecute方法里,OAuth2RestTemplate类是RestTemplate的子类。估计是用了反射吧。)
好吧,下面来看OAuth2RestTemplate的doExecute方法里都做了些什么。
首先第一行代码
OAuth2AccessToken accessToken = context.getAccessToken();
会去DefaultOAuth2ClientContext取得一个accessToken,那么这个accessToken是什么呢?
简单来说,accessToken就是令牌,当用户登录了sparklr系统并授权后就会生成一个accessToken,再之后tonr凭这个accessToken就可以拿到sparklr里的相片。
好了,第一次accessToken肯定是为null的,接下来代码会直接执行父类RestTemplate的doexcute方法。
RestTemplate的doexcute方法里会执行createRequest方法,如上面一样,会执行OAuth2RestTemplate类里的createRequest方法。(不太懂)
OAuth2AccessToken accessToken = getAccessToken();
看到上面的代码了吧?getAccessToken就是取得token的核心代码。
但是spring在这个方法里又嵌套了很多层,并没有所有代码都写在这个方法里。相信看过Spring源码的同学一定对这种方式不陌生。
getAccessToken里又调用了acquireAccessToken方法。而acquireAccessToken里又调用了obtainAccessToken方法。
这里要注意的是,obtainAccessToken方法实现执行的是
AuthorizationCodeAccessTokenProvider类里的方法。
这个方法里有一个判断,如下:
if (request.getAuthorizationCode() == null) {
if (request.getStateKey() == null) {
throw getRedirectForAuthorization(resource, request);
}
obtainAuthorizationCode(resource, request);
}第一次进来这两个if肯定都满足,执行getRedirectForAuthorization方法,到方法里去看,会发现实际抛出的是UserRedirectRequiredException异常。
这个异常会被
