SSO analysis of OAuth2 using JWT

Reference: https://github.com/spring-guides/tut-spring-security-and-angular-js/blob/master/oauth2/README.adoc
http://jwt.io/introduction/
This article is in <Using OAuth2 Based on the SSO analysis > article, the use of jwt can reduce the request to the authentication server, but jwt is much longer than swt (Simple Web Tokens), and it also relies on public key decryption.
write picture description here
1. The browser clicks to the UI server Trigger requires security
authentication
_
_ UI server 7. The UI server forwards the /resource/ request to the Resource server . The Resource server takes out the accessToken from the request, decodes it, and directly converts it into authentication and authorization information for judgment (finally, it will respond to the UI server, and the UI server will then respond to the browser)



The main difference between this and <SSO analysis using OAuth2> is that the accessToken is jwt, which can be converted into authentication and authorization information after decoding and conversion. The custom login page and authorization page have also been modified, and this solution is starting to be close to production.

1. First create the OAuth2 authorization server
1. Because a custom page is used, the wro4j-maven-plugin plugin and the following dependencies are added to pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2. The main class modification is relatively large, the main class inherits WebMvcConfigurerAdapter mainly to register the view controller; the inner class inheriting WebSecurityConfigurerAdapter mainly modifies the custom permission control; the key is to inherit the authorization server configuration of AuthorizationServerConfigurerAdapter, which is configured with JwtAccessTokenConverter (the key is here Use), and use this Bean; @EnableResourceServer is also placed on the main class.
3. The application configuration moves the oauth configuration to the OAuth2AuthorizationConfig inner class. A keystore file and two freemarker pages are added. After
starting the authorization server, It can be tested:
a. Open the browser and enter the address http://localhost:9999/uaa/oauth/authorize?response_type=code&client_id=acme&redirect_uri=http://example.com to make a request, and then enter the username/ Password, click Agree to get the returned authorization code
b. Enter
[root@dev ~]#curl acme:[email protected]:9999/uaa/oauth/token \
-d grant_type= authorization_code -d client_id=acme \
-d redirect_uri= http: //example.com -d code=fjRdsL
Enter acquired access token, wherein the license code acquired fjRdsL replacement step returns the result similar to the following:
{"access_token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0NTk1NTUxNTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIiwiUk9MRV9VU0VSIl0sImp0aSI6IjI5MjcyYWJiLTQ4MjUtNGYwMS1hZjllLTg5ZGE1ZDE1MDBiNyIsImNsaWVudF9pZCI6ImFjbWUiLCJzY29wZSI6WyJvcGVuaWQiXX0.cQd88GYItHUDJuwkd_Rd0Yo8QM1R0dccuK0-xZ4OynC7EnqClLunaNOZ9jXwtilIFJNxbkbhQ8ymXdvlAF5Zjo8lpRGotdVo9rgQc39BDse7hGy1EfA9ZADQmJ-EuwkTNo0IBEXYC33XxQNK_3I_E92cnIPXq-FZHuZMRzpr-SlriwLa3aZVidmeyXK2U5dsjViWoHHKhcg-9c-VBPtyTJfPZOvj3s7DrbfCgOAGOhHkd_MBCdLDFb7QFhzIRsMfcD9rOAGTqk-hU2pHkkakKQ7_vL604UU7Qh3Zzkn6VbHPy0HAAiB9cnUhkQxK3Qb-wbHG-l3FC2pDlhtlhMHNfg","token_type":"bearer","refresh_token":"eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6IjI5MjcyYWJiLTQ4MjUtNGYwMS1hZjllLTg5ZGE1ZDE1MDBiNyIsImV4cCI6MTQ2MjEwMzk1NiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiJdLCJqdGkiOiIzNWM5OWY0Yy0xMGM0LTQ5ZTAtODAwYi1lZTc5ZTQ3ODNkNmUiLCJjbGllbnRfaWQiOiJhY21lIn0.bUvJ9HmrFU92euLzd5eesJKFlav5v1WyfBEgd3pO6I2D2yYy98oPwfNwCrbP44M2ilO48LJEovLLoZFYvjfA8xe6XO1Fx55Tik5SrWfizAEsNFsFg25zE92T3YNocStxuJWFSVBLlwjtxpVmnHOgPefku2G6N5seziX0SOBJleHSUObNAYtiBVQjKWXA3jGnMoZSP0dMbgtrWinwRJLwvaMgMDNnxYFSdvSW99XKjCyQNVmbGa4aRyy-xblTr7qlSqdcZIdRBfKkHM5S9jaenNVc85vGAYQFPrdkRWhk4v-8nlHJiYdBa6ZspgbVWw_oPLgP8cbuzJev86q55p1gAw","expires_in":43199,"scope":"openid","jti":"29272abb-4825-4f01-af9e-89da5d1500b7"}
Copy access_token return results from the continued:
[the root @ dev ~] # = eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0NTk1NTUxNTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIiwiUk9MRV9VU0VSSI6IjI5MjcyYWJiLTQ4MjUtNGYwMS1hZjllLTg5ZGE1ZDE1MDBiNyIsImNsaWVudF9pZCI6ImFjbWUiLCJzY29wZSI6WyJvcGVuaWQiXX0.cQd88GYItHUDJuwkd_Rd0Yo8QM1R0dccuK0 the TOKEN-xZ4OynC7EnqClLunaNOZ9jXwtilIFJNxbkbhQ8ymXdvlAF5Zjo8lpRGotdVo9rgQc39BDse7hGy1EfA9ZADQmJ-EuwkTNo0IBEXYC33XxQNK_3I_E92cnIPXq-FZHuZMRzpr 9C-VBPtyTJfPZOvj3s7DrbfCgOAGOhHkd_MBCdLDFb7QFhzIRsMfcD9rOAGTqk---SlriwLa3aZVidmeyXK2U5dsjViWoHHKhcg hU2pHkkakKQ7_vL604UU7Qh3Zzkn6VbHPy0HAAiB9cnUhkQxK3Qb-wbHG-l3FC2pDlhtlhMHNfg
[the root @ dev ~] # -H curl "the Authorization: Bearer the TOKEN $" 192.168.1.115:9999/uaa/user
second command returns results similar to the following:
{"details":{"remoteAddress":"192.168.1.194","sessionId":null,"tokenValue":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0NTk1NTUxNTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIiwiUk9MRV9VU0VSIl0sImp0aSI6IjI5MjcyYWJiLTQ4MjUtNGYwMS1hZjllLTg5ZGE1ZDE1MDBiNyIsImNsaWVudF9pZCI6ImFjbWUiLCJzY29wZSI6WyJvcGVuaWQiXX0.cQd88GYItHUDJuwkd_Rd0Yo8QM1R0dccuK0-xZ4OynC7EnqClLunaNOZ9jXwtilIFJNxbkbhQ8ymXdvlAF5Zjo8lpRGotdVo9rgQc39BDse7hGy1EfA9ZADQmJ-EuwkTNo0IBEXYC33XxQNK_3I_E92cnIPXq-FZHuZMRzpr-SlriwLa3aZVidmeyXK2U5dsjViWoHHKhcg-9c-VBPtyTJfPZOvj3s7DrbfCgOAGOhHkd_MBCdLDFb7QFhzIRsMfcD9rOAGTqk-hU2pHkkakKQ7_vL604UU7Qh3Zzkn6VbHPy0HAAiB9cnUhkQxK3Qb-wbHG-l3FC2pDlhtlhMHNfg","tokenType":"Bearer","decodedDetails":null},"authorities":[{"authority":"ROLE_ADMIN"},{"authority":"ROLE_USER"}],"authenticated":true,"userAuthentication":{"details":null,"authorities":[{"authority":"ROLE_ADMIN"},{"authority":"ROLE_USER"}],"authenticated":true,"principal":"user","credentials":"N/A","name":"user"},"credentials":"","principal":"user","oauth2Request":{"clientId":"acme","scope":["openid"],"requestParameters":{"client_id":"acme"},"resourceIds":[],"authorities":[],"approved":true,"refresh":false,"redirectUri":null,"responseTypes":[],"extensions":{},"grantType":null,"refreshTokenRequest":null},"clientOnly":false,"name":"user"}
From the results, everything is normal to use the access token to access resources, indicating that the authorization server is fine.

2. Look at the separate resource server
spring-security-jwt dependency and also add pom.xml; the main class has not changed; the application configuration file uses security.oauth2.resource.jwt.keyValue to replace the security.oauth2.resource.userInfoUri option, use This public key to decrypt jwt.

Finally, run the main method test of the main class (the authorization server is started before, and the access_token is also obtained), so I use the curl command:
[root@dev ~]# curl -H "Authorization: Bearer $TOKEN" 192.168.1.115:9000
returns The results are similar to the following:
{"id":"03af8be3-2fc3-4d75-acf7-c484d9cf32b1","content":"Hello World"}
Track the process of obtaining authentication and authorization information:
When a request is made using curl -H "Authorization: Bearer $TOKEN" 192.168.1.115:9000, until it is processed by the OAuth2AuthenticationProcessingFilter interceptor,
org.springframework.security.oauth2.provider .authentication.OAuth2AuthenticationProcessingFilter#doFilter{
Authentication authentication = tokenExtractor.extract(request);//Extract Token
Authentication authResult = authenticationManager.authenticate(authentication);//Restore decoding authentication and authorization information
}
org.springframework.security.oauth2.provider.authentication .OAuth2AuthenticationManager#authenticate{
OAuth2Authentication auth = tokenServices.loadAuthentication(token);//这里的tokenServices是DefaultTokenServices
}
org.springframework.security.oauth2.provider.token.DefaultTokenServices#loadAuthentication{
OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue);//tokenStore是JwtTokenStore
OAuth2Authentication result = tokenStore.readAuthentication(accessToken);
}
org.springframework.security.oauth2.provider.token.store.JwtTokenStore#readAccessToken{
OAuth2AccessToken accessToken = convertAccessToken(tokenValue);
}
org.springframework.security.oauth2.provider.token.store.JwtTokenStore#convertAccessToken{
return jwtTokenEnhancer.extractAccessToken(tokenValue, jwtTokenEnhancer.decode(tokenValue));
}
org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter#extractAccessToken
After the above process, use jwt's public key to decode jwt, and extract from it OAuth2Authentication, this Authentication itself contains user authentication information. There is no need to send a request to the authorization server for decoding

3. The UI server is used as the client of SSO.
Similarly, the UI server should also add spring-security-jwt dependency to pom.xml; the main class is basically unchanged; like the resource server, use security.oauth2.resource.jwt.keyValue to replace security.oauth2.resource.userInfoUri option. Other analysis is similar to <SSO analysis using OAuth2>. Test can be started on all three servers.

 

http://m.fx114.net/qa-235-319551.aspx

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326719503&siteId=291194637