首页 > 编程 > Java > 正文

Spring Security OAuth2 token权限隔离实例解析

2019-11-26 08:20:33
字体:
来源:转载
供稿:网友

这篇文章主要介绍了Spring Security OAuth2 token权限隔离实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

由于项目OAuth2采用了多种模式,授权码模式为第三方系统接入,密码模式用于用户登录,Client模式用于服务间调用,

所有不同的模式下的token需要用 @PreAuthorize("hasAuthority('client')") 进行隔离,遇到问题一直验证不通过。

通过调试发现资源服务从授权服务拿到的authrities字段一直为空, StackOverFlow说低版本(项目中才2.0.15)的OAuth2实现权限隔离需要 重写UserInfoTokenService

但是资源服务太多所以考虑重写授权服务的返回值,如何重写?在哪里重写?是下面要介绍的~

一、哪里重写?

资源服务器向授权服务服务器获取资源时候,返回的user信息重写,加入authorities

@RestController@Slf4jpublic class UserController { @Autowired HttpServletRequest request; @GetMapping("/user") public Principal user(Principal principal) {  log.info("获取user信息:{}", JSON.toJSON(principal));  return principal; }

返回的具体用户信息:

{  "principal": {    "password": "$2a$10$OjTFAZEzS6qypY4nRZtnM.MzS6F3XsIlkAO/kIFCu30kAk8Yasowa",    "phone": "13918438965",    "credentialsNonExpired": true,    "accountNonExpired": true,    "enabled": true,    "accountNonLocked": true,    "username": "4738195728608789333"  },  "authenticated": true,  "oAuth2Request": {    "redirectUri": "http://www.baidu.com",    "responseTypes": ["code"],    "approved": true,    "extensions": {},    "clientId": "external",    "scope": ["auth_base"],    "requestParameters": {      "code": "ovzMSk",      "grant_type": "authorization_code",      "scope": "auth_base",      "response_type": "code",      "redirect_uri": "http://www.baidu.com",      "state": "123",      "client_secret": "D524C1A0811DA49592F841085CC0063EB62B3001252A9454",      "client_id": "external"    },    "refresh": false,    "grantType": "authorization_code",    "authorities": [{      "authority": "auth_base"    }],    "resourceIds": []  },  "clientOnly": false,  "credentials": "",  "name": "4738195728608789333",  "userAuthentication": {    "principal": {      "password": "$2a$10$OjTFAZEzS6qypY4nRZtnM.MzS6F3XsIlkAO/kIFCu30kAk8Yasowa",      "phone": "13918438965",      "credentialsNonExpired": true,      "accountNonExpired": true,      "enabled": true,      "accountNonLocked": true,      "username": "4738195728608789333"    },    "authenticated": true,    "oAuth2Request": {      "responseTypes": [],      "approved": true,      "extensions": {},      "clientId": "gt",      "scope": ["frontend"],      "requestParameters": {        "auth_type": "sms",        "device_id": "5c5d1d7b-50ae-4347-9aee-7a7686055f4d",        "grant_type": "password",        "client_id": "gt",        "username": "13918438965"      },      "refresh": false,      "grantType": "password",      "authorities": [{        "authority": "client"      }],      "resourceIds": []    },    "clientOnly": false,    "credentials": "",    "name": "4738195728608789333",    "userAuthentication": {      "principal": {        "password": "$2a$10$OjTFAZEzS6qypY4nRZtnM.MzS6F3XsIlkAO/kIFCu30kAk8Yasowa",        "phone": "13918438965",        "credentialsNonExpired": true,        "accountNonExpired": true,        "enabled": true,        "accountNonLocked": true,        "username": "4738195728608789333"      },      "authenticated": true,      "name": "4738195728608789333",      "details": {        "auth_type": "sms",        "device_id": "5c5d1d7b-50ae-4347-9aee-7a7686055f4d",        "grant_type": "password",        "client_secret": "D524C1A0811DA49592F841085CC0063EB62B3001252A94542795D1CA9824A941",        "client_id": "gt",        "username": "13918438965"      },      "authorities": []    },    "details": {      "tokenType": "Bearer",      "tokenValue": "f7870e71-7b0f-4a4a-9c6f-bb6d1f903ad9",      "remoteAddress": "0:0:0:0:0:0:0:1"    },    "authorities": []  },  "details": {    "tokenType": "Bearer",    "tokenValue": "7829005c-5ebe-4428-b951-89477b24316e",    "remoteAddress": "0:0:0:0:0:0:0:1"  },  "authorities": []}

二、如何重写?

principal是OAuth2Authentication实例,OAuth2Authentication主要包括OAuth2Request storedRequest、Authentication userAuthentication,

重写目的是将storedRequest authorities复制到authoritie中,但问题是authoritie不让修改的,没办法只能重写这个OAuth2Authentication了。

为了改变authoritie重写:

@GetMapping("/user") public Principal user(Principal principal) {  log.info("获取user信息:{}", JSON.toJSON(principal));  OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) principal;  OAuth2Request storedRequest = oAuth2Authentication.getOAuth2Request();  Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();  // 为了服务端进行token权限隔离 定制OAuth2Authentication  CustomOAuth2Authentication customOAuth2Authentication = new CustomOAuth2Authentication(storedRequest, userAuthentication, storedRequest.getAuthorities());  customOAuth2Authentication.setDetails(oAuth2Authentication.getDetails());  log.info("返回用户信息:{}", JSON.toJSON(customOAuth2Authentication));  return customOAuth2Authentication; }

CustomOAuth2Authentication :

package com.brightcns.wuxi.citizencard.auth.domain;import org.springframework.security.authentication.AbstractAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.CredentialsContainer;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.oauth2.provider.OAuth2Request;import java.util.Collection;/** * @author maxianming * @date 2018/10/29 13:53 */public class CustomOAuth2Authentication extends AbstractAuthenticationToken {  private static final long serialVersionUID = -4809832298438307309L;  private final OAuth2Request storedRequest;  private final Authentication userAuthentication;  /**   * Construct an OAuth 2 authentication. Since some grant types don't require user authentication, the user   * authentication may be null.   * @param storedRequest   The authorization request (must not be null).   * @param userAuthentication The user authentication (possibly null).   */  public CustomOAuth2Authentication(OAuth2Request storedRequest, Authentication userAuthentication, Collection<? extends GrantedAuthority> authorities) {    /**     * 为了服务端进行token权限隔离 {@link @PreAuthorize("hasAuthority('server')")},自定义OAuth2Authentication使得支持改变authorities     */    super(authorities != null ? authorities : userAuthentication == null ? storedRequest.getAuthorities() : userAuthentication.getAuthorities());    this.storedRequest = storedRequest;    this.userAuthentication = userAuthentication;  }  public Object getCredentials() {    return "";  }  public Object getPrincipal() {    return this.userAuthentication == null ? this.storedRequest.getClientId() : this.userAuthentication        .getPrincipal();  }  /**   * Convenience method to check if there is a user associated with this token, or just a client application.   *   * @return true if this token represents a client app not acting on behalf of a user   */  public boolean isClientOnly() {    return userAuthentication == null;  }  /**   * The authorization request containing details of the client application.   *   * @return The client authentication.   */  public OAuth2Request getOAuth2Request() {    return storedRequest;  }  /**   * The user authentication.   *   * @return The user authentication.   */  public Authentication getUserAuthentication() {    return userAuthentication;  }  @Override  public boolean isAuthenticated() {    return this.storedRequest.isApproved()        && (this.userAuthentication == null || this.userAuthentication.isAuthenticated());  }  @Override  public void eraseCredentials() {    super.eraseCredentials();    if (this.userAuthentication != null && CredentialsContainer.class.isAssignableFrom(this.userAuthentication.getClass())) {      CredentialsContainer.class.cast(this.userAuthentication).eraseCredentials();    }  }  @Override  public boolean equals(Object o) {    if (this == o) {      return true;    }    if (!(o instanceof CustomOAuth2Authentication)) {      return false;    }    if (!super.equals(o)) {      return false;    }    CustomOAuth2Authentication that = (CustomOAuth2Authentication) o;    if (!storedRequest.equals(that.storedRequest)) {      return false;    }    if (userAuthentication != null ? !userAuthentication.equals(that.userAuthentication)        : that.userAuthentication != null) {      return false;    }    if (getDetails() != null ? !getDetails().equals(that.getDetails()) : that.getDetails() != null) {      // return false;    }    return true;  }  @Override  public int hashCode() {    int result = super.hashCode();    result = 31 * result + storedRequest.hashCode();    result = 31 * result + (userAuthentication != null ? userAuthentication.hashCode() : 0);    return result;  }}

主要在OAuth2Authentication基础上修改了30-35行代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表