使用JWT的Spring Boot OAuth2授权服务器刷新令牌

时间:2019-05-11 07:00:40

标签: spring-boot spring-security oauth-2.0 spring-security-oauth2 spring-cloud-security

我已将Spring Boot Oauth2授权服务器配置为独立服务器。对于启用了JWT的grant_type passwordclient_credentials等来说,它工作正常。但是,当我使用grant_type=refresh_token时,即使refresh_token过期或两次发送了refresh_token(配置为不重用refresh_token),授权服务器也会成功地进行响应。

下面是邮递员控制台的示例输出。

获取JWT令牌

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"993b222c-6b94-4eb9-b458-36ec5d3a2ed5"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:52
Request Body:
    username:"admin"
    password:"password"
    grant_type:"password"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:43:42 GMT"
Response Body:
access_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTc1OTMwMjIsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiI0MjFiZDJjNC01ODAxLTRiOTktYTk2MS04YzVjNjZiMzA1NjUiLCJjbGllbnRfaWQiOiJjbGllbnRfMSIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il19.42B_TUfZ5fZAYFZQmSY4smvH_aIH9nsnoOzvMiGs2q0"
    token_type:"bearer"
refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImF0aSI6IjQyMWJkMmM0LTU4MDEtNGI5OS1hOTYxLThjNWM2NmIzMDU2NSIsImV4cCI6MTU1NzU5MzAyMiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiI5MGZkMDg5YS0xZmZjLTRkOWItOTk2ZS0zOWMyZmEzM2E1YzkiLCJjbGllbnRfaWQiOiJjbGllbnRfMSJ9.hfZl6p8IBzMjDCJ6UZHB-LVTv4gZJxuRKx_H867i0F4"
    expires_in:35999
    scope:"read write trust"
    jti:"421bd2c4-5801-4b99-a961-8c5c66b30565"

从刷新令牌获取新的访问令牌

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"15b00c4d-d9fd-409e-b787-dd14c9fc8a59"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:415
Request Body:
    refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImF0aSI6IjQyMWJkMmM0LTU4MDEtNGI5OS1hOTYxLThjNWM2NmIzMDU2NSIsImV4cCI6MTU1NzU5MzAyMiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiI5MGZkMDg5YS0xZmZjLTRkOWItOTk2ZS0zOWMyZmEzM2E1YzkiLCJjbGllbnRfaWQiOiJjbGllbnRfMSJ9.hfZl6p8IBzMjDCJ6UZHB-LVTv4gZJxuRKx_H867i0F4"
    grant_type:"refresh_token"
    scope:"read"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:44:02 GMT"
Response Body:
    access_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTc1OTMwNDIsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiI1YmM5OGM3NC1iZDdlLTQ4MDktYjg5Yi1hOTEwYWZiZDMzOGQiLCJjbGllbnRfaWQiOiJjbGllbnRfMSIsInNjb3BlIjpbInJlYWQiXX0.dF8m_j-1xOnQb4ccPc2YNF77UBTcIIZlFsTi7EO-cfQ"
    token_type:"bearer"
    refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiXSwiYXRpIjoiNWJjOThjNzQtYmQ3ZS00ODA5LWI4OWItYTkxMGFmYmQzMzhkIiwiZXhwIjoxNTU3NTkzMDQyLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6Ijg5MWFkY2I1LWY1OWYtNDMzMS1iNWFhLTRmMzcxNzU5MDFjZSIsImNsaWVudF9pZCI6ImNsaWVudF8xIn0.gUIZCsBMLIR2K8_WO2v9zwKxE5OYbMqt3UQGIFb3SBs"
    expires_in:35999
    scope:"read"
    jti:"5bc98c74-bd7e-4809-b89b-a910afbd338d"

使用示例刷新令牌重试(现在它以sccess响应,理想情况下应该以无效的refresh_token响应)

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"53190109-bf08-4b12-a2dd-37216beed103"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:415
Request Body:
    refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il0sImF0aSI6IjQyMWJkMmM0LTU4MDEtNGI5OS1hOTYxLThjNWM2NmIzMDU2NSIsImV4cCI6MTU1NzU5MzAyMiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiI5MGZkMDg5YS0xZmZjLTRkOWItOTk2ZS0zOWMyZmEzM2E1YzkiLCJjbGllbnRfaWQiOiJjbGllbnRfMSJ9.hfZl6p8IBzMjDCJ6UZHB-LVTv4gZJxuRKx_H867i0F4"
    grant_type:"refresh_token"
    scope:"read"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:44:04 GMT"
Response Body:
    access_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTc1OTMwNDQsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiIxNjliZjU2NS0yZTQyLTQ5NDktYTcwMC1lMWMxOTg1ZTM2NTkiLCJjbGllbnRfaWQiOiJjbGllbnRfMSIsInNjb3BlIjpbInJlYWQiXX0._hO1doe0FfH_OC4EoRv67vznbToeRvHh_9t2HY5pN0M"
    token_type:"bearer"
    refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiXSwiYXRpIjoiMTY5YmY1NjUtMmU0Mi00OTQ5LWE3MDAtZTFjMTk4NWUzNjU5IiwiZXhwIjoxNTU3NTkzMDQ0LCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQwN2E0ZGM1LWU4M2YtNDVlYS04ZDdjLWMwNmQyZGEzNDQ5MyIsImNsaWVudF9pZCI6ImNsaWVudF8xIn0.02WvhOH3Y5vx9-NTtppupBePWKTUHHejYkbLQ3iCMEA"
    expires_in:35999
    scope:"read"
    jti:"169bf565-2e42-4949-a700-e1c1985e3659"

没有JWT的工作示例

获取令牌

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"b1ef5f14-30bf-4df5-9a1b-57eedc8ad25c"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:52
Request Body:
    username:"admin"
    password:"password"
    grant_type:"password"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:35:49 GMT"
Response Body:
    access_token:"3e026c95-2b67-47a0-a305-0e7e4bb2690d"
    token_type:"bearer"
    refresh_token:"5bdfb8e2-3248-400f-b860-13f1318d9a34"
    expires_in:36000
    scope:"read write trust"

刷新令牌

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"ed9ac62f-ddad-4c42-9286-9fbd82cb1414"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:86
Request Body:
    refresh_token:"5bdfb8e2-3248-400f-b860-13f1318d9a34"
    grant_type:"refresh_token"
    scope:"read"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:43:11 GMT"
Response Body:
    access_token:"73dc3f14-38f4-419d-b457-1233108100a5"
    token_type:"bearer"
    refresh_token:"ad48ff61-f8c3-41ac-abb2-08dc212f3c14"
    expires_in:35999
    scope:"read"

使用相同的刷新令牌重试(现在出现无效令牌错误)

Request Headers:
    Content-Type:"application/x-www-form-urlencoded"
    cache-control:"no-cache"
    Postman-Token:"98fe827b-168b-45d1-bd6a-ee6cbb27a098"
    Authorization:"Basic Y2xpZW50XzE6c2VjcmV0"
    User-Agent:"PostmanRuntime/7.6.0"
    Accept:"*/*"
    Host:"localhost:8080"
    cookie:"JSESSIONID=25D2C296A51FA2BD39D9C6B5724AC85D"
    accept-encoding:"gzip, deflate"
    content-length:86
Request Body:
    refresh_token:"5bdfb8e2-3248-400f-b860-13f1318d9a34"
    grant_type:"refresh_token"
    scope:"read"
Response Headers:
    Access-Control-Allow-Origin:"*"
    Access-Control-Allow-Methods:"POST, PUT, GET, OPTIONS, DELETE"
    Access-Control-Allow-Headers:"Authorization, Content-Type"
    Access-Control-Max-Age:"3600"
    Pragma:"no-cache"
    Cache-Control:"no-store"
    X-Content-Type-Options:"nosniff"
    X-XSS-Protection:"1; mode=block"
    X-Frame-Options:"DENY"
    Content-Type:"application/json;charset=UTF-8"
    Transfer-Encoding:"chunked"
    Date:"Sat, 11 May 2019 06:43:13 GMT"
    Connection:"close"
Response Body:
    error:"invalid_grant"
    error_description:"Invalid refresh token: 5bdfb8e2-3248-400f-b860-13f1318d9a34"

这是我的AuthConfig.java

@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(AuthorizationServerProperties.class)
@Import({ AuthorizationServerTokenServicesConfiguration.class, AuthorizationServerEndpointsConfiguration.class })
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private AuthorizationServerProperties authorization;

    @Autowired(required = false)
    private TokenStore tokenStore;

    @Autowired(required = false)
    private AccessTokenConverter tokenConverter;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder).build();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
        if (this.authorization.getCheckTokenAccess() != null) {
            security.checkTokenAccess(this.authorization.getCheckTokenAccess());
        }
        if (this.authorization.getTokenKeyAccess() != null) {
            security.tokenKeyAccess(this.authorization.getTokenKeyAccess());
        }
        if (this.authorization.getRealm() != null) {
            security.realm(this.authorization.getRealm());
        }
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager).userDetailsService(userDetailsService)
                .reuseRefreshTokens(false);
        if (this.tokenConverter != null) {
            endpoints.accessTokenConverter(this.tokenConverter);
        }
        if (this.tokenStore != null) {
            endpoints.tokenStore(this.tokenStore);
        }
    }

}

application.yml

spring:
  application:
    name: auth-server
security:
  oauth2:
    authorization:
      check-token-access: "isAuthenticated()"
      jwt:
        key-value: 12345

任何能解决此问题的见解都将受到赞赏。

0 个答案:

没有答案