可见token根据UUID生成的 所以token里面的信息是无意义的 看上节redis里面token的存储,是把相关信息与token做了关联 如过redis服务器挂掉了,那么这个token就是毫无意义的,以为他本身不包含任何信息
jwt 恰恰相反,它是自包含了相关的信息
密签的意思 不是 jwt 信息的加密或解密
他是指如果 jwt 里面的信息被修改以后 我们能够通过密签发现
jwt不能存储敏感信息
可以在里面放任何数据
这个配置里面配置了两个TokenStore 根据不同的配置确认token的类型 默认是JwtTokenStore
@Configuration public class TokenStoreConfig { @Autowired private RedisConnectionFactory redisConnectionFactory; @Bean @ConditionalOnProperty(prefix = "whale.security.oauth2",name = "storeType",havingValue = "redis",matchIfMissing = false) public TokenStore tokenStore(){ return new RedisTokenStore(redisConnectionFactory); } @Configuration @ConditionalOnProperty(prefix = "whale.security.oauth2",name = "storeType",havingValue = "jwt",matchIfMissing = true) //prefix 是只application配置文件中 配置的最后一个点分隔后前面的一部分 这叫前缀 //name 对应的是后缀 最后一个点分隔后的后面的那部分 //即检查的配置项为 whale.security.oauth2.storeType //havingValue = "jwt" 当配置项的值为jwt的时候 这个类里面的所有配置生效 //matchIfMissing 如果配置文件里没有找到这个属性,即默认生效 public static class JwtTokenConfig{ @Autowired private SecurityProperties securityProperties; //token 的存储 @Bean public TokenStore jwtTokenStore(){ return new JwtTokenStore(jwtAccessTokenConverter()); } //token生成处理 @Bean public JwtAccessTokenConverter jwtAccessTokenConverter(){ JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); jwtAccessTokenConverter.setSigningKey(securityProperties.getOauth2().getJwtSigningKey()); return jwtAccessTokenConverter; } } }用表单登录获取token的方式 发现 这次的 access_token 很长
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTg2MDg5NjQsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiYWRtaW4iLCJST0xFX1VTRVIiXSwianRpIjoiMzYzNjJiZWUtMjFjOS00ZWM3LWIxMmUtYjQyYzYyYzViZjI5IiwiY2xpZW50X2lkIjoid2hhbGUiLCJzY29wZSI6WyJhbGwiLCJyZWFkIiwid3JpdGUiXX0.PJ1vcPCccfVfrHxCJzRs19xoFV6hnu5lMetJuYARylw",https://jwt.io/ jwt解析 访问资源成功
WhaleTokenEnhancer
public class WhaleTokenEnhancer implements TokenEnhancer { /** * * @param oAuth2AccessToken * @param oAuth2Authentication * @return */ @Override public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) { Map<String,Object> info = new HashMap<>(); info.put("company","埃森哲"); ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(info); return oAuth2AccessToken; } }部分代码如下
@Autowired(required = false) private TokenEnhancer jwtTokenEnhancer; /** * * @param endpoints oauth/token 的入口点 * @throws Exception */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // super.configure(endpoints); // endpoints.authenticationManager(authenticationManager).userDetailsService(userDetailsService); endpoints.tokenStore(tokenStore) .authenticationManager(authenticationManager) .userDetailsService(userDetailsService); if(jwtAccessTokenConverter!=null && jwtTokenEnhancer!=null){ TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); List<TokenEnhancer> enhancers = new ArrayList<>(); enhancers.add(jwtTokenEnhancer); enhancers.add(jwtAccessTokenConverter); tokenEnhancerChain.setTokenEnhancers(enhancers); endpoints.tokenEnhancer(tokenEnhancerChain) .accessTokenConverter(jwtAccessTokenConverter); } }eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCIsInJlYWQiLCJ3cml0ZSJdLCJjb21wYW55Ijoi5ZD5qOu5ZOyIiwiZXhwIjoxNTU4NjEzNjQzLCJhdXRob3JpdGllcyI6WyJhZG1pbiIsIlJPTEVfVVNFUiJdLCJqdGkiOiI5OTA3NWZjOC04MTI3LTQ2YWYtYTM2OS0wNTlkODlkNTIwMTEiLCJjbGllbnRfaWQiOiJ3aGFsZSJ9.1Ild0mbgxQn1No0NQIQI2gWrTDFDcgdHYHdC_kdGq_w
解析如下
注意 虽然我们的jwt可以携带额外信息 但是 我们的spring 只是 将 jwt规范里面的信息解析成 Authentication 如果我们需要jwt token 里的额外信息呢?
为此我们需要加入新的依赖
https://jwt.io/ https://www.jsonwebtoken.io/
试了几个 0.9.0 版本可以
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>
在用户无感的情况下用refresh_token得到一个新的token
但我的refresh_token没有测试成功 也不知道什么原因
按道理是完全可以的,也不知道问题出在哪
https://auth0.com/docs/tokens/refresh-token/current#9e51c5c22d4b450cab209018dc3be588_java
Use a Refresh Token To exchange the Refresh Token you received during authorization for a new Access Token, make a POST request to the /oauth/token endpoint in the Authentication API, using grant_type=refresh_token.
curl --request POST \ --url 'https://YOUR_DOMAIN/oauth/token' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=refresh_token&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&refresh_token=YOUR_REFRESH_TOKEN'https://openapi.baidu.com/wiki/index.php?title=使用Refresh_Token获取Access_Token
https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
https://auth0.com/docs/tokens/refresh-token/current
https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#acquiring--client-ids-and-secrets