Shiro学习(一)——OAuth2集成

OAuth角色 
资源拥有者(resource owner):能授权访问受保护资源的一个实体,可以是一个人,那我们称之为最终用户;如新浪微博用户zhangsan; 
资源服务器(resource server):存储受保护资源,客户端通过access token请求资源,资源服务器响应受保护资源给客户端;存储着用户zhangsan的微博等信息。 
授权服务器(authorization server):成功验证资源拥有者并获取授权之后,授权服务器颁发授权令牌(Access Token)给客户端。 
客户端(client):如新浪微博客户端weico、微格等第三方应用,也可以是它自己的官方应用;其本身不存储资源,而是资源拥有者授权通过后,使用它的授权(授权令牌)访问受保护资源,然后客户端把相应的数据展示出来/提交到服务器。“客户端”术语不代表任何特定实现(如应用运行在一台服务器、桌面、手机或其他设备)。

OAuth2协议流程

Shiro学习(一)——OAuth2集成_第1张图片 
1、客户端从资源拥有者那请求授权。授权请求可以直接发给资源拥有者,或间接的通过授权服务器这种中介,后者更可取。 
2、客户端收到一个授权许可,代表资源服务器提供的授权。 
3、客户端使用它自己的私有证书及授权许可到授权服务器验证。 
4、如果验证成功,则下发一个访问令牌。 
5、客户端使用访问令牌向资源服务器请求受保护资源。 
6、资源服务器会验证访问令牌的有效性,如果成功则下发受保护资源。

更多流程的解释请参考OAuth2的协议规范http://tools.ietf.org/html/rfc6749。

服务器端 
本文把授权服务器和资源服务器整合在一起实现。

POM依赖 
此处我们使用apache oltu oauth2服务端实现,需要引入authzserver(授权服务器依赖)和resourceserver(资源服务器依赖)。 
Java代码

<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>org.apache.oltu.oauth2<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>org.apache.oltu.oauth2.authzserver<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>0.31<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>  
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span>  
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>org.apache.oltu.oauth2<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>org.apache.oltu.oauth2.resourceserver<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>  
    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>0.31<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>  
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span>   </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

其他的请参考pom.xml。

数据字典 
用户(oauth2_user) 
Shiro学习(一)——OAuth2集成_第2张图片 
客户端(oauth2_client) 
Shiro学习(一)——OAuth2集成_第3张图片

用户表存储着认证/资源服务器的用户信息,即资源拥有者;比如用户名/密码;客户端表存储客户端的的客户端id及客户端安全key;在进行授权时使用。

表及数据SQL 
具体请参考 
sql/ shiro-schema.sql (表结构) 
sql/ shiro-data.sql (初始数据)

默认用户名/密码是admin/123456。

实体 
具体请参考com.github.zhangkaitao.shiro.chapter17.entity包下的实体,此处就不列举了。

DAO 
具体请参考com.github.zhangkaitao.shiro.chapter17.dao包下的DAO接口及实现。

Service 
具体请参考com.github.zhangkaitao.shiro.chapter17.service包下的Service接口及实现。以下是出了基本CRUD之外的关键接口: 
Java代码

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> UserService {  
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> User <span class="hljs-title" style="box-sizing: border-box;">createUser</span>(User user);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建用户  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> User <span class="hljs-title" style="box-sizing: border-box;">updateUser</span>(User user);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 更新用户  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deleteUser</span>(Long userId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 删除用户  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">changePassword</span>(Long userId, String newPassword); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//修改密码  </span>
    User findOne(Long userId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据id查找用户  </span>
    List<User> findAll();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 得到所有用户  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> User <span class="hljs-title" style="box-sizing: border-box;">findByUsername</span>(String username);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据用户名查找用户  </span>
}  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

Java代码

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> ClientService {  
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Client <span class="hljs-title" style="box-sizing: border-box;">createClient</span>(Client client);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建客户端  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Client <span class="hljs-title" style="box-sizing: border-box;">updateClient</span>(Client client);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 更新客户端  </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deleteClient</span>(Long clientId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 删除客户端  </span>
    Client findOne(Long clientId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据id查找客户端  </span>
    List<Client> findAll();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 查找所有  </span>
    Client findByClientId(String clientId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据客户端id查找客户端  </span>
    Client findByClientSecret(String clientSecret);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//根据客户端安全KEY查找客户端  </span>
}  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

Java代码

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OAuthService</span> {</span>  
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">addAuthCode</span>(String authCode, String username);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 添加 auth code  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">addAccessToken</span>(String accessToken, String username); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 添加 access token  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> checkAuthCode(String authCode); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 验证auth code是否有效  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> checkAccessToken(String accessToken); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 验证access token是否有效  </span>
   String getUsernameByAuthCode(String authCode);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据auth code获取用户名  </span>
   String getUsernameByAccessToken(String accessToken);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据access token获取用户名  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> getExpireIn();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//auth code / access token 过期时间  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">checkClientId</span>(String clientId);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 检查客户端id是否存在  </span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">checkClientSecret</span>(String clientSecret);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 坚持客户端安全KEY是否存在  </span>
}   </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

此处通过OAuthService实现进行auth code和access token的维护。

后端数据维护控制器 
具体请参考com.github.zhangkaitao.shiro.chapter17.web.controller包下的IndexController、LoginController、UserController和ClientController,其用于维护后端的数据,如用户及客户端数据;即相当于后台管理。

授权控制器AuthorizeController 
Java代码

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Controller</span>  
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AuthorizeController</span> {</span>  
  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Autowired</span>  
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> OAuthService oAuthService;  
  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Autowired</span>  
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ClientService clientService;  
  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@RequestMapping</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/authorize"</span>)  
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">authorize</span>(Model model,  HttpServletRequest request)  
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> URISyntaxException, OAuthSystemException {  
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//构建OAuth 授权请求  </span>
      OAuthAuthzRequest oauthRequest = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OAuthAuthzRequest(request);  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//检查传入的客户端id是否正确  </span>
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!oAuthService.checkClientId(oauthRequest.getClientId())) {  
        OAuthResponse response = OAuthASResponse  
             .errorResponse(HttpServletResponse.SC_BAD_REQUEST)  
             .setError(OAuthError.TokenResponse.INVALID_CLIENT)  
             .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)  
             .buildJSONMessage();  
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ResponseEntity(  
           response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));  
      }  

      Subject subject = SecurityUtils.getSubject();  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果用户没有登录,跳转到登陆页面  </span>
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!subject.isAuthenticated()) {  
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!login(subject, request)) {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//登录失败时跳转到登陆页面  </span>
          model.addAttribute(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"client"</span>,      
              clientService.findByClientId(oauthRequest.getClientId()));  
          <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"oauth2login"</span>;  
        }  
      }  

      String username = (String)subject.getPrincipal();  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生成授权码  </span>
      String authorizationCode = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//responseType目前仅支持CODE,另外还有TOKEN  </span>
      String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (responseType.equals(ResponseType.CODE.toString())) {  
        OAuthIssuerImpl oauthIssuerImpl = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OAuthIssuerImpl(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MD5Generator());  
        authorizationCode = oauthIssuerImpl.authorizationCode();  
        oAuthService.addAuthCode(authorizationCode, username);  
      }  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进行OAuth响应构建  </span>
      OAuthASResponse.OAuthAuthorizationResponseBuilder builder =  
        OAuthASResponse.authorizationResponse(request,   
                                           HttpServletResponse.SC_FOUND);  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置授权码  </span>
      builder.setCode(authorizationCode);  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//得到到客户端重定向地址  </span>
      String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);  

      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//构建响应  </span>
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> OAuthResponse response = builder.location(redirectURI).buildQueryMessage();  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//根据OAuthResponse返回ResponseEntity响应  </span>
      HttpHeaders headers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HttpHeaders();  
      headers.setLocation(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> URI(response.getLocationUri()));  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));  
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (OAuthProblemException e) {  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//出错处理  </span>
      String redirectUri = e.getRedirectUri();  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (OAuthUtils.isEmpty(redirectUri)) {  
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//告诉客户端没有传入redirectUri直接报错  </span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ResponseEntity(  
          <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"OAuth callback url needs to be provided by client!!!"</span>, HttpStatus.NOT_FOUND);  
      }  
      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//返回错误消息(如?error=)  </span>
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> OAuthResponse response =  
              OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND)  
                      .error(e).location(redirectUri).buildQueryMessage();  
      HttpHeaders headers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HttpHeaders();  
      headers.setLocation(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> URI(response.getLocationUri()));  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));  
    }  
  }  

  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">login</span>(Subject subject, HttpServletRequest request) {  
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"get"</span>.equalsIgnoreCase(request.getMethod())) {  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;  
    }  
    String username = request.getParameter(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"username"</span>);  
    String password = request.getParameter(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"password"</span>);  

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;  
    }  

    UsernamePasswordToken token = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UsernamePasswordToken(username, password);  
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {  
      subject.login(token);  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;  
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {  
      request.setAttribute(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"error"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"登录失败:"</span> + e.getClass().getName());  
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;  
    }  
  }  
}   </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li></ul>

如上代码的作用: 
1、首先通过如http://localhost:8080/chapter17-server/authorize 
?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee&response_type=code&redirect_uri=http://localhost:9080/chapter17-client/oauth2-login访问授权页面; 
2、该控制器首先检查clientId是否正确;如果错误将返回相应的错误信息; 
3、然后判断用户是否登录了,如果没有登录首先到登录页面登录; 
4、登录成功后生成相应的auth code即授权码,然后重定向到客户端地址,如http://localhost:9080/chapter17-client/oauth2-login?code=52b1832f5dff68122f4f00ae995da0ed;在重定向到的地址中会带上code参数(授权码),接着客户端可以根据授权码去换取access token。

访问令牌控制器AccessTokenController 

你可能感兴趣的:(Shiro学习(一)——OAuth2集成)