spring security只适合单机,spring security oauth2才是分布式的选择,分布式下我肯定搞jwt,要不然得考虑分布式session,jwt续签问题,不着急,慢慢来。
1.认证服务器配置token为jwt
package com.stackcloud.system.config;
import com.stackcloud.system.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import javax.sql.DataSource;
import java.util.Arrays;
/**
* 认证服务器配置
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private SysUserService sysUserService;
@Autowired
private TokenEnhancer tokenEnhancer;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
/**
* <pre>
* 我们配置了使用数据库来维护客户端信息。虽然在各种 Demo 中我们经常看到的是在内存中维护客户端信息, 通过配置直接写死在这里。
*
* 但是,对于实际的应用我们一般都会用数据库来维护这个信息,甚至还会建立一套工作流来允许客户端自己申请 ClientID,实现 OAuth 客户端接入的审批。
* </pre>
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
/**
* 这里干了两件事儿。
* 首先,打开了验证 Token 的访问权限(以便之后我们演示)。
* 然后,允许 ClientSecret 明文方式保存,并且可以通过表单提交(而不仅仅是 BasicAuth方式提交),之后会演示到这个。
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()")
.allowFormAuthenticationForClients()
.passwordEncoder(passwordEncoder);
}
/**
* <pre>
* 干了以下4件事儿:
* 1. 配置我们的令牌存放方式为 JWT方式,而不是内存、数据库或 Redis方式。
* JWT 是 Json Web Token 的缩写,也就是使用 JSON 数据格式包装的令牌,由 .号把整个 JWT分隔为头、数据体、签名三部分。
* JWT保存 Token 虽然易于使用但是不是那么安全,一般用于内部,且需要走 HTTPS 并配置比较短的失效时间。
* 2. 配置 JWT Token 的非对称加密来进行签名
* 3. 配置一个自定义的 Token 增强器,把更多信息放入 Token 中
* 4. 配置使用 JDBC 数据库方式来保存用户的授权批准记录
* </pre>
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//CustomTokenEnhancer 自定义的Token增强器,把更多信息放入Token中
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, jwtAccessTokenConverter));
endpoints
//使用 JDBC 数据库方式来保存用户的授权批准记录
.approvalStore(new JdbcApprovalStore(dataSource))
//数据库保存授权码
.authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource))
//使用jwt
.tokenStore(new JwtTokenStore(jwtAccessTokenConverter))
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager)
.userDetailsService(sysUserService);
}
}
2.JwtAccessTokenConverter研究
基于RSA无非就是私钥和公钥,看下源码
public void setKeyPair(KeyPair keyPair) {
PrivateKey privateKey = keyPair.getPrivate();
Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA ");
signer = new RsaSigner((RSAPrivateKey) privateKey);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
verifier = new RsaVerifier(publicKey);
verifierKey = "-----BEGIN PUBLIC KEY-----n" + new String(Base64.encode(publicKey.getEncoded()))
+ "n-----END PUBLIC KEY-----";
}
/**
* Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys
* should be in OpenSSH format, as produced by <tt>ssh-keygen</tt>.
*
* @param key the key to be used for signing JWTs.
*/
public void setSigningKey(String key) {
Assert.hasText(key);
key = key.trim();
this.signingKey = key;
if (isPublic(key)) {
signer = new RsaSigner(key);
logger.info("Configured with RSA signing key");
}
else {
// Assume it's a MAC key
this.verifierKey = key;
signer = new MacSigner(key);
}
}
如果要用RSA得按OPENSSH得格式,需要用ssh-keygen生成,所谓格式就是上面得开头是 -----BEGIN PUBLIC KEY-----,结尾是-----END PUBLIC KEY-----。
3.生成RSA 密钥对
在linux上,随便搞个虚拟机都可以,基于java得 keygen下次再研究。
[root@localhost test]# openssl rsa -in jwt.pem
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqI/1ah3MdXUeSxKSlYqalvk9Kdns8K8cqKDaJ5qz0RCJw+CA
T032iaGL1PuK/hIbNaarLBzB0SZPxp5v1UE/ERnLfYiq+yFlTfp3FniWKEjdWby1
vvvWJYtYNb+zuk07gVLOzONAX/ZdOaZVtwUm/+lEU5wcHk6GnSvM/q8KYJJ/2VXG
kuXw7sQDok1deVuDsN7DBbXhfahYAdWupC22fy5RRPm8ea8oOxif/eZxzkgWicco
BgFExdiOZMTXg3y8LxDl2c23FRXYegT8ZmxANyjvuVDIchTmkqbMoa6SkRVL8B3W
esEpB35Ag8g6h71CMT6S2mUMgFBlU7JgSIM5SQIDAQABAoIBAHfafI6qh4GQ+Cw7
FX09I3Rr3eCPMtlkOcVxMgztBCSIVNyxGarJ7Z2o/ys+fHLxXuWED7v66pkTW7AH
Yc9JaFV5eOZWsfSEp2qNx/VzYplcTf+LndMhcAAcF2mIWHwEhGYNAjxO7awOGfVu
3w2WnUdjjpDAtIGcJj1FMqp4vbEx8kn/4ogeBZp2+tnHATQiU976ML0jxjcEAKMW
7unefDN1wmaVf8r0Glvef1YVjtZCVPVBkYs2GVsSvi44wka0Nkj/4mdk5QtOcb6s
XMKjqU1kUeCslSB2T7xHaknU+Xwo/skRWkMaOWO4ZQDrqunRu5QvfQQtnE25O37e
lguYu4ECgYEA0LBUKh6pEgFcWFutf3igWElGoH0OjwEaKdptvMYmGtC/YGViwhvn
t9JhUu44pUDt9tKJ6h8poB7xr6aQa05dEAbrN7paYTn/KsxBSOIj/vh8InNKCLFo
V9MU45qMikF8f57LSvIF5o4NVJstKQGWa45XPMdxTzNg3+9RUgiHJRkCgYEAzsbP
sVGsitly3nICRSVcLaT4JkXvfwk0EcGv+lha9TZR266w6V3LzgshyK1FbM8ukDTm
Fe5Q0zzHpeqjU4yhPxnCIIFXPQBVQxyZT0M2eN44E35pNTZ3liJS0r5/4n9HhPiM
n1eBZFwVhOlPjDkC6yZzD7Z6olXxO+AHyhEei7ECgYEAnhFxLpYaqbCuKZ8HQ04y
5axa+qS+qkLDdoAkLqBHrHgA/RrOOwi38tw/K3mVHlaX6CSAof0IomfN2KXpLd4l
T0ZuU7+rRYmQZPJhYLspWK8OF2oL4Zm+1wbjA6LEYNRJYMD+ar33CjL+ld8TzcOO
E9m06iyG/t6DuhqjFeevtcECgYAqWRFEMYPy0+HwqMzKOIKOXpDr1brc+5eMY2yV
Cu9l9QACy94zjSAmTKVYohPr2uqgYhUVPL+U44fH9SwJ+m0zrSTS32psddsAaaUE
VLGdQ3WcmHEXktYfC1yHCLjMPGD7XKQAJj27vhgyJk5CW5K7ch5yg17OTGehaZpu
yd7FoQKBgQCPvldGHOyCUl4NqW/r7NQI2h5DEAGyFZNqttcse0zLjScVeksFKgeX
dMIXZT84tMWHnfbDV3zH3PKw8OKruICbaF273ayl3ntmlAqfqmmQtbiKH880hJV4
SWeSmF+YNsmblmxSVYGNjvb+gYyesKLseYJE1YfEEedrFo87KaV6Kg==
-----END RSA PRIVATE KEY-----
[root@localhost test]# openssl rsa -in jwt.pem -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqI/1ah3MdXUeSxKSlYqa
lvk9Kdns8K8cqKDaJ5qz0RCJw+CAT032iaGL1PuK/hIbNaarLBzB0SZPxp5v1UE/
ERnLfYiq+yFlTfp3FniWKEjdWby1vvvWJYtYNb+zuk07gVLOzONAX/ZdOaZVtwUm
/+lEU5wcHk6GnSvM/q8KYJJ/2VXGkuXw7sQDok1deVuDsN7DBbXhfahYAdWupC22
fy5RRPm8ea8oOxif/eZxzkgWiccoBgFExdiOZMTXg3y8LxDl2c23FRXYegT8ZmxA
NyjvuVDIchTmkqbMoa6SkRVL8B3WesEpB35Ag8g6h71CMT6S2mUMgFBlU7JgSIM5
SQIDAQAB
-----END PUBLIC KEY-----
[root@localhost test]#
4.添加到配置文件
security:
oauth2:
jwt:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqI/1ah3MdXUeSxKSlYqalvk9Kdns8K8cqKDaJ5qz0RCJw+CA
T032iaGL1PuK/hIbNaarLBzB0SZPxp5v1UE/ERnLfYiq+yFlTfp3FniWKEjdWby1
vvvWJYtYNb+zuk07gVLOzONAX/ZdOaZVtwUm/+lEU5wcHk6GnSvM/q8KYJJ/2VXG
kuXw7sQDok1deVuDsN7DBbXhfahYAdWupC22fy5RRPm8ea8oOxif/eZxzkgWicco
BgFExdiOZMTXg3y8LxDl2c23FRXYegT8ZmxANyjvuVDIchTmkqbMoa6SkRVL8B3W
esEpB35Ag8g6h71CMT6S2mUMgFBlU7JgSIM5SQIDAQABAoIBAHfafI6qh4GQ+Cw7
FX09I3Rr3eCPMtlkOcVxMgztBCSIVNyxGarJ7Z2o/ys+fHLxXuWED7v66pkTW7AH
Yc9JaFV5eOZWsfSEp2qNx/VzYplcTf+LndMhcAAcF2mIWHwEhGYNAjxO7awOGfVu
3w2WnUdjjpDAtIGcJj1FMqp4vbEx8kn/4ogeBZp2+tnHATQiU976ML0jxjcEAKMW
7unefDN1wmaVf8r0Glvef1YVjtZCVPVBkYs2GVsSvi44wka0Nkj/4mdk5QtOcb6s
XMKjqU1kUeCslSB2T7xHaknU+Xwo/skRWkMaOWO4ZQDrqunRu5QvfQQtnE25O37e
lguYu4ECgYEA0LBUKh6pEgFcWFutf3igWElGoH0OjwEaKdptvMYmGtC/YGViwhvn
t9JhUu44pUDt9tKJ6h8poB7xr6aQa05dEAbrN7paYTn/KsxBSOIj/vh8InNKCLFo
V9MU45qMikF8f57LSvIF5o4NVJstKQGWa45XPMdxTzNg3+9RUgiHJRkCgYEAzsbP
sVGsitly3nICRSVcLaT4JkXvfwk0EcGv+lha9TZR266w6V3LzgshyK1FbM8ukDTm
Fe5Q0zzHpeqjU4yhPxnCIIFXPQBVQxyZT0M2eN44E35pNTZ3liJS0r5/4n9HhPiM
n1eBZFwVhOlPjDkC6yZzD7Z6olXxO+AHyhEei7ECgYEAnhFxLpYaqbCuKZ8HQ04y
5axa+qS+qkLDdoAkLqBHrHgA/RrOOwi38tw/K3mVHlaX6CSAof0IomfN2KXpLd4l
T0ZuU7+rRYmQZPJhYLspWK8OF2oL4Zm+1wbjA6LEYNRJYMD+ar33CjL+ld8TzcOO
E9m06iyG/t6DuhqjFeevtcECgYAqWRFEMYPy0+HwqMzKOIKOXpDr1brc+5eMY2yV
Cu9l9QACy94zjSAmTKVYohPr2uqgYhUVPL+U44fH9SwJ+m0zrSTS32psddsAaaUE
VLGdQ3WcmHEXktYfC1yHCLjMPGD7XKQAJj27vhgyJk5CW5K7ch5yg17OTGehaZpu
yd7FoQKBgQCPvldGHOyCUl4NqW/r7NQI2h5DEAGyFZNqttcse0zLjScVeksFKgeX
dMIXZT84tMWHnfbDV3zH3PKw8OKruICbaF273ayl3ntmlAqfqmmQtbiKH880hJV4
SWeSmF+YNsmblmxSVYGNjvb+gYyesKLseYJE1YfEEedrFo87KaV6Kg==
-----END RSA PRIVATE KEY-----
publicKey: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqI/1ah3MdXUeSxKSlYqa
lvk9Kdns8K8cqKDaJ5qz0RCJw+CAT032iaGL1PuK/hIbNaarLBzB0SZPxp5v1UE/
ERnLfYiq+yFlTfp3FniWKEjdWby1vvvWJYtYNb+zuk07gVLOzONAX/ZdOaZVtwUm
/+lEU5wcHk6GnSvM/q8KYJJ/2VXGkuXw7sQDok1deVuDsN7DBbXhfahYAdWupC22
fy5RRPm8ea8oOxif/eZxzkgWiccoBgFExdiOZMTXg3y8LxDl2c23FRXYegT8ZmxA
NyjvuVDIchTmkqbMoa6SkRVL8B3WesEpB35Ag8g6h71CMT6S2mUMgFBlU7JgSIM5
SQIDAQAB
-----END PUBLIC KEY-----
5.JwtAccessTokenConverter设置
/**
* 配置 JWT 使用非对称加密方式来验证
*
* @return
*/
@Bean
protected JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(jwtPrivateKey);
converter.setVerifierKey(jwtPublicKey);
return converter;
}
SigningKey就是私钥,用私钥来签名,就是生成token的,VerifierKey就是公钥,等下jwt token进来 用公钥验签。
6.测试
获取token
http://localhost:9011/oauth/token?username=admin&grant_type=password&client_id=userservice1&client_secret=1234&password=admin
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidXNlcnNlcnZpY2UiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJGT08iXSwiZXhwIjoxNjU4NjM1Nzg1LCJ1c2VyRGV0YWlscyI6eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiJDJhJDEwJDhFM01yTVcvY0RISldmLkNxSkpLcHVnaDVjQjZYNFlvZlQvQmkvNXZ6S1JKTGZiYVV4ckppIiwicm9sZUxpc3QiOm51bGwsImxvY2tlZCI6ZmFsc2UsImVuYWJsZWQiOnRydWUsImV4cGlyZWQiOmZhbHNlLCJhdXRob3JpdGllcyI6bnVsbCwiYWNjb3VudE5vbkxvY2tlZCI6dHJ1ZSwiY3JlZGVudGlhbHNOb25FeHBpcmVkIjp0cnVlLCJhY2NvdW50Tm9uRXhwaXJlZCI6dHJ1ZSwiY3JlZGVudGlhbHMiOnRydWV9LCJqdGkiOiI1Nzg1MjBmOS1iY2RlLTQxNGQtYjQyOS02N2ExZThiZmQ3NmYiLCJjbGllbnRfaWQiOiJ1c2Vyc2VydmljZTEifQ.Ibnf2rPlgpfcdUtQbJaqxGDXBegEPWTW4Xx0eDdMDyVtmc1fosIfXDiMfvBeTBe8ROWzOva9NrU57xBHOm-Nhr4xfnT44QE7X7dejYJ5CjRhRvVfiFlYvMO_8tZeGjPR3EuyIxnQia4uYQpIDn65yyagVYKALzLMVtiADzD10aS9dzrW5PQOtWMzM4DFI6GeIZlq_qhsX-NUsYFQYoTtaWFXEqzlPDZTrpI6LAvn9ZRui0kfz0h06Zy_5EC0ogRUTS-T-S4oOFs4sUi_MNb7gJFP8kts7BXQYndtXH_Djsm4GaytU6AjdW96mVKArrCMAlar45gBKPorvdlJt7qs3w",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidXNlcnNlcnZpY2UiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJGT08iXSwiYXRpIjoiNTc4NTIwZjktYmNkZS00MTRkLWI0MjktNjdhMWU4YmZkNzZmIiwiZXhwIjoxNjYxMjIwNTg1LCJ1c2VyRGV0YWlscyI6eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiJDJhJDEwJDhFM01yTVcvY0RISldmLkNxSkpLcHVnaDVjQjZYNFlvZlQvQmkvNXZ6S1JKTGZiYVV4ckppIiwicm9sZUxpc3QiOm51bGwsImxvY2tlZCI6ZmFsc2UsImVuYWJsZWQiOnRydWUsImV4cGlyZWQiOmZhbHNlLCJhdXRob3JpdGllcyI6bnVsbCwiYWNjb3VudE5vbkxvY2tlZCI6dHJ1ZSwiY3JlZGVudGlhbHNOb25FeHBpcmVkIjp0cnVlLCJhY2NvdW50Tm9uRXhwaXJlZCI6dHJ1ZSwiY3JlZGVudGlhbHMiOnRydWV9LCJqdGkiOiJmNjU3ODVmMS0xNDI5LTQ1Y2MtOWRkZS04MTRiM2VkYmZjZmYiLCJjbGllbnRfaWQiOiJ1c2Vyc2VydmljZTEifQ.YhjHRbAmsSlh0gc1CzrRbMz918CQ42giW9a8MXPvF5y3Eg4fl_KwKjaZjhgKE8wnZr8ueDQxK46pviQwwzwfN5UBt1VgJahPEVUX2mtREEwdPl5MYZESMSx8pYDZopqMLD1qHpzrjkf45AbONVAECP6srfR-324lXxCd2ldA3jbwfxsexotQDawvC7UuQYn6N3KFV-P8QBpz9KE7dnkqEIFbMMzjtvzO-_u-_4A-tnCwXFxVULxXMawghLbjOb8jEoq0NbqOXHZxVlvigCDNy55x0OH74PU__SCmqp4qs05zJ5TANDM6OPvF2pAvbpD_b-oZzH3pA2mWNtqqPWkHpw",
"expires_in": 7199,
"scope": "FOO",
"userDetails": {
"id": 1,
"username": "admin",
"password": "$2a$10$8E3MrMW/cDHJWf.CqJJKpugh5cB6X4YofT/Bi/5vzKRJLfbaUxrJi",
"locked": false,
"enabled": true,
"expired": false,
"accountNonLocked": true,
"credentialsNonExpired": true,
"accountNonExpired": true,
"credentials": true
},
"jti": "578520f9-bcde-414d-b429-67a1e8bfd76f"
}
验证token
http://localhost:9011/oauth/check_token?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidXNlcnNlcnZpY2UiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJGT08iXSwiZXhwIjoxNjU4NjMzODQ1LCJ1c2VyRGV0YWlscyI6eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiJDJhJDEwJDhFM01yTVcvY0RISldmLkNxSkpLcHVnaDVjQjZYNFlvZlQvQmkvNXZ6S1JKTGZiYVV4ckppIiwicm9sZUxpc3QiOm51bGwsImxvY2tlZCI6ZmFsc2UsImVuYWJsZWQiOnRydWUsImV4cGlyZWQiOmZhbHNlLCJhdXRob3JpdGllcyI6bnVsbCwiYWNjb3VudE5vbkxvY2tlZCI6dHJ1ZSwiY3JlZGVudGlhbHNOb25FeHBpcmVkIjp0cnVlLCJhY2NvdW50Tm9uRXhwaXJlZCI6dHJ1ZSwiY3JlZGVudGlhbHMiOnRydWV9LCJqdGkiOiIzY2ZiMmE1NC01NjQzLTQ1YWEtYjZkZi01ZmY5MzIxN2U5MTQiLCJjbGllbnRfaWQiOiJ1c2Vyc2VydmljZTEifQ.gjb_otXav_FHzGqKo4KMNbQLNu0BXzbSmIR9_kl0BN2zFnKfCRm6oJKgquhwNv6U0M7UEFLhDlCC594Nuy8XDrdrGpkAb03t4fGQB_zqZscbD--n5kKLYP8yNb1FYrgS90d9p4Elfi4_IkS34nBKOmfmI-NS17ePAQBWXoQTEpTk8QJ3Nuh_OWSlG7EZoRsevCtD4OlRawLCCWhTIdUVKbTQeJz_V2qOrJKtu0jiTWIom_77CfaEd2sSF-s28ZndsEH1mOwd7KZlCUm_cGn1QnpFI_MEQLXWDzsZDY3Ctv97vX26gVlNCh8WUQhx4gsMdA7r53ClzQZld6FIV7pWQg
{
"aud": [
"userservice"
],
"user_name": "admin",
"scope": [
"FOO"
],
"active": true,
"exp": 1658633845,
"userDetails": {
"id": 1,
"username": "admin",
"password": "$2a$10$8E3MrMW/cDHJWf.CqJJKpugh5cB6X4YofT/Bi/5vzKRJLfbaUxrJi",
"locked": false,
"enabled": true,
"expired": false,
"accountNonLocked": true,
"credentialsNonExpired": true,
"accountNonExpired": true,
"credentials": true
},
"jti": "3cfb2a54-5643-45aa-b6df-5ff93217e914",
"client_id": "userservice1"
}
7.异构系统之间的token使用
假如其他系统基于我这个权限验证,比如python,其他java程序,当然是可以的,因为spring security oauth2 jwt 也是标准的。
比如我基于java jwt
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
使用标准jwt来解析
String ftoken="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidXNlcnNlcnZpY2UiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJGT08iXSwiZXhwIjoxNjU4NjMzODQ1LCJ1c2VyRGV0YWlscyI6eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiJDJhJDEwJDhFM01yTVcvY0RISldmLkNxSkpLcHVnaDVjQjZYNFlvZlQvQmkvNXZ6S1JKTGZiYVV4ckppIiwicm9sZUxpc3QiOm51bGwsImxvY2tlZCI6ZmFsc2UsImVuYWJsZWQiOnRydWUsImV4cGlyZWQiOmZhbHNlLCJhdXRob3JpdGllcyI6bnVsbCwiYWNjb3VudE5vbkxvY2tlZCI6dHJ1ZSwiY3JlZGVudGlhbHNOb25FeHBpcmVkIjp0cnVlLCJhY2NvdW50Tm9uRXhwaXJlZCI6dHJ1ZSwiY3JlZGVudGlhbHMiOnRydWV9LCJqdGkiOiIzY2ZiMmE1NC01NjQzLTQ1YWEtYjZkZi01ZmY5MzIxN2U5MTQiLCJjbGllbnRfaWQiOiJ1c2Vyc2VydmljZTEifQ.gjb_otXav_FHzGqKo4KMNbQLNu0BXzbSmIR9_kl0BN2zFnKfCRm6oJKgquhwNv6U0M7UEFLhDlCC594Nuy8XDrdrGpkAb03t4fGQB_zqZscbD--n5kKLYP8yNb1FYrgS90d9p4Elfi4_IkS34nBKOmfmI-NS17ePAQBWXoQTEpTk8QJ3Nuh_OWSlG7EZoRsevCtD4OlRawLCCWhTIdUVKbTQeJz_V2qOrJKtu0jiTWIom_77CfaEd2sSF-s28ZndsEH1mOwd7KZlCUm_cGn1QnpFI_MEQLXWDzsZDY3Ctv97vX26gVlNCh8WUQhx4gsMdA7r53ClzQZld6FIV7pWQg";
String pkeyd=
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqI/1ah3MdXUeSxKSlYqan" +
"lvk9Kdns8K8cqKDaJ5qz0RCJw+CAT032iaGL1PuK/hIbNaarLBzB0SZPxp5v1UE/n" +
"ERnLfYiq+yFlTfp3FniWKEjdWby1vvvWJYtYNb+zuk07gVLOzONAX/ZdOaZVtwUmn" +
"/+lEU5wcHk6GnSvM/q8KYJJ/2VXGkuXw7sQDok1deVuDsN7DBbXhfahYAdWupC22n" +
"fy5RRPm8ea8oOxif/eZxzkgWiccoBgFExdiOZMTXg3y8LxDl2c23FRXYegT8ZmxAn" +
"NyjvuVDIchTmkqbMoa6SkRVL8B3WesEpB35Ag8g6h71CMT6S2mUMgFBlU7JgSIM5n" +
"SQIDAQABn" ;
DecodedJWT decodedJWT = JWT.require(Algorithm.RSA256((RSAPublicKey)RSAUtil.getPublicKeyByBase64Code(pkeyd),null)).build().verify(ftoken);
String userId= decodedJWT.getClaim("user_name").asString();
System.out.println(userId);
注意要把publickey前缀后缀去掉,测试了一下,完全没问题