精华内容
下载资源
问答
  • oauth2刷新tokenInvalid refresh token

    千次阅读 2019-03-27 14:41:26
    刷新token报错如下图: 看源码DefaultTokenServices发现里面有个属性 private int refreshTokenValiditySeconds = 2592000; private int accessTokenValiditySeconds = 43200; private boolean ...

    刷新token报错如下图:

    看源码DefaultTokenServices发现里面有个属性

    private int refreshTokenValiditySeconds = 2592000;
    private int accessTokenValiditySeconds = 43200;
    private boolean supportRefreshToken = false;
    private boolean reuseRefreshToken = true;
    private TokenStore tokenStore;
    private ClientDetailsService clientDetailsService;
    private TokenEnhancer accessTokenEnhancer;
    private AuthenticationManager authenticationManager;
    

    设置之后成功

    setSupportRefreshToken(true);
    展开全文
  • "nodejs.ForbiddenError: invalid csrf token" 对此问题官方有说明 点击跳转egg官方安全说明 这里不做过多解释 方法一:在confit.default.js新增以下代码,表示关闭安全验证(不推荐) config.security = { csrf: ...

    不得不说阿里的egg框架做的还是相当不错的,自带安全验证。

    问题: get请求正常,post请求后台就会报这样的错误。

    "nodejs.ForbiddenError: invalid csrf token"

    对此问题官方有说明 点击跳转egg官方安全说明 这里不做过多解释

    方法一:在confit.default.js新增以下代码,表示关闭安全验证(不推荐)

    在这里插入图片描述

    config.security = {
        csrf: {
          enable: false,
        },
      };
    
    方法二: 在前端初始化界面的时候,让前端先get请求一个接口,后台返回一个秘钥给前端,让前端在post请求的时候放在headers请求头里,egg会自动去验证这个秘钥,验证成功才会成功请求。
    1、egg后台代码,get接口返回秘钥:
    async index() {
        const { ctx } = this;
        ctx.body = {
          csrf:ctx.csrf
        };
    }
    

    以下演示两种方式,postman测试如下,同时如果在前端请求的话,cookies里面会生成一个秘钥对,如下图,每次请求后秘钥都会变的,所以在前端获取到csrf要以全局的方式放在headers请求头里。
    在这里插入图片描述

    在这里插入图片描述

    2、前端带上秘钥请求:
    axios.post('apis/add', data,{headers:{'x-csrf-token': headData}})
    

    postman测试如下,直接复制csrf
    在这里插入图片描述

    好了,请求成功,完美解决,开始搬砖
    展开全文
  • 同clientId多端登录下jwt+auth2+security使用RedisTokenStore刷新token后长token不可用:Invalid refresh token问题

    原文链接https://blog.csdn.net/weixin_41546244/article/details/112554788

    背景,环境

    springSecurity+jwt+auth2

    修改前的配置:

    @Bean
        public TokenStore redisTokenStore() {
            // 使用redis存储token
            RedisTokenStore redisTokenStore = new RedisCover(connectionFactory);
            // 设置redis token存储中的前缀
            redisTokenStore.setPrefix(RedisKeysConstant.USER_TOKENS);
            return redisTokenStore;
        }
    
        @Bean
        public DefaultTokenServices tokenService() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            // 配置token存储
            tokenServices.setTokenStore(redisTokenStore());
            // 开启支持refresh_token,此处如果之前没有配置,启动服务后再配置重启服务,可能会导致不返回token的问题,解决方式:清除redis对应token存储
            tokenServices.setSupportRefreshToken(true);
            // 复用refresh_token
            tokenServices.setReuseRefreshToken(true);
            // token有效期,设置2小时
            tokenServices.setAccessTokenValiditySeconds(2 * 60 * 60);
            // refresh_token有效期,设置一周
            tokenServices.setRefreshTokenValiditySeconds(15 * 24 * 60 * 60);
    
            // 通过TokenEnhancerChain增强器链将jwtAccessTokenConverter(转换成jwt)和jwtTokenEnhancer(往里面加内容加信息)连起来
            TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
            List<TokenEnhancer> enhancerList = new ArrayList<>();
            enhancerList.add(jwtAccessTokenConverter);
            enhancerChain.setTokenEnhancers(enhancerList);
            tokenServices.setTokenEnhancer(enhancerChain);
    
            return tokenServices;
        }
    

    redis存储的结构:
    在这里插入图片描述

    问题描述:

    1.正常调用登录接口,返回accessToken,refreshToken,此时使用refreshToken调用刷新token接口,返回的refreshToken无法作为刷新token的参数。
    2.A使用账号登录后保存refreshToken,规定时间后accesstoken过期,使用refreshtoken刷新accesstoken,虽然此处可以选择不保留刷新后得到的refreshtoken进行续期,保留之前的旧refreshtoken(也就是长token过期必退出策略),但是多端登录下,另一个人B是使用同账号登录,得到的是A刷新后的token,而1情况问题得到证实。

    原因分析

    从RedisTokenStore存储的结构以及源码可知,accessToken、refreshToken相互的关系获得的方式存储的key为:access_to_refresh:*,refresh_to_access:*两个key获得。
    但是刷新token时候源码可知:
    DefaultTokenServices-refreshAccessToken():

    @Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class})
    	public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)
    			throws AuthenticationException {
    
    		if (!supportRefreshToken) {
    			throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
    		}
    
    		OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
    		if (refreshToken == null) {
    			throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
    		}
    
    		OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken);
    		if (this.authenticationManager != null && !authentication.isClientOnly()) {
    			// The client has already been authenticated, but the user authentication might be old now, so give it a
    			// chance to re-authenticate.
    			Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities());
    			user = authenticationManager.authenticate(user);
    			Object details = authentication.getDetails();
    			authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user);
    			authentication.setDetails(details);
    		}
    		String clientId = authentication.getOAuth2Request().getClientId();
    		if (clientId == null || !clientId.equals(tokenRequest.getClientId())) {
    			throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue);
    		}
    
    		// clear out any access tokens already associated with the refresh
    		// token.
    		tokenStore.removeAccessTokenUsingRefreshToken(refreshToken);
    
    		if (isExpired(refreshToken)) {
    			tokenStore.removeRefreshToken(refreshToken);
    			throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken);
    		}
    
    		authentication = createRefreshedAuthentication(authentication, tokenRequest);
    
    		if (!reuseRefreshToken) {
    			tokenStore.removeRefreshToken(refreshToken);
    			refreshToken = createRefreshToken(authentication);
    		}
    
    		OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
    		tokenStore.storeAccessToken(accessToken, authentication);
    		if (!reuseRefreshToken) {
    			tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
    		}
    		return accessToken;
    	}
    

    注意tokenStore.readRefreshToken这个方法:
    RedisTokenStore-readRefreshToken():

    	@Override
    	public OAuth2RefreshToken readRefreshToken(String tokenValue) {
    		byte[] key = serializeKey(REFRESH + tokenValue);
    		byte[] bytes = null;
    		RedisConnection conn = getConnection();
    		try {
    			bytes = conn.get(key);
    		} finally {
    			conn.close();
    		}
    		OAuth2RefreshToken refreshToken = deserializeRefreshToken(bytes);
    		return refreshToken;
    	}
    

    可知校验时候是从REFRESHkey(refresh:*) 的值找到refreshtoken;
    但是每次刷新token,刷新的token会在此处获得一个新的refreshToken保存到:

    private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
    		DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
    		int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
    		if (validitySeconds > 0) {
    			token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
    		}
    		token.setRefreshToken(refreshToken);
    		token.setScope(authentication.getOAuth2Request().getScope());
    
    		return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
    	}
    

    由于我们有设置增强链:tokenServices.setTokenEnhancer(enhancerChain);则这个方法的必然会重新生成一个新的refreshToken。

    思路

    1.让每次刷新返回的refreshtoken都保持一开始的,也就是说到点必然退出的策略,但是存在问题,如果一个人A登录得到了长token后开始计时,下一个人登录还是使用之前的token那可能正好在过期时间点,则会退出,舍弃此思路。

    2.因为打断点可以看到刷新token追回保存以下几个key值:
    refreshAccessToken方法中有:tokenStore.storeAccessToken(accessToken, authentication);
    storeAccessToken:

    @Override
    	public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
    		byte[] serializedAccessToken = serialize(token);
    		byte[] serializedAuth = serialize(authentication);
    		byte[] accessKey = serializeKey(ACCESS + token.getValue());
    		byte[] authKey = serializeKey(AUTH + token.getValue());
    		byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication));
    		byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication));
    		byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId());
    
    		RedisConnection conn = getConnection();
    		try {
    			conn.openPipeline();
    			if (springDataRedis_2_0) {
    				try {
    					this.redisConnectionSet_2_0.invoke(conn, accessKey, serializedAccessToken);
    					this.redisConnectionSet_2_0.invoke(conn, authKey, serializedAuth);
    					this.redisConnectionSet_2_0.invoke(conn, authToAccessKey, serializedAccessToken);
    				} catch (Exception ex) {
    					throw new RuntimeException(ex);
    				}
    			} else {
    				conn.set(accessKey, serializedAccessToken);
    				conn.set(authKey, serializedAuth);
    				conn.set(authToAccessKey, serializedAccessToken);
    			}
    			if (!authentication.isClientOnly()) {
    				conn.sAdd(approvalKey, serializedAccessToken);
    			}
    			conn.sAdd(clientId, serializedAccessToken);
    			if (token.getExpiration() != null) {
    				int seconds = token.getExpiresIn();
    				conn.expire(accessKey, seconds);
    				conn.expire(authKey, seconds);
    				conn.expire(authToAccessKey, seconds);
    				conn.expire(clientId, seconds);
    				conn.expire(approvalKey, seconds);
    			}
    			OAuth2RefreshToken refreshToken = token.getRefreshToken();
    			if (refreshToken != null && refreshToken.getValue() != null) {
    				byte[] refresh = serialize(token.getRefreshToken().getValue());
    				byte[] auth = serialize(token.getValue());
    				byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue());
    				byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue());
    				if (springDataRedis_2_0) {
    					try {
    						this.redisConnectionSet_2_0.invoke(conn, refreshToAccessKey, auth);
    						this.redisConnectionSet_2_0.invoke(conn, accessToRefreshKey, refresh);
    					} catch (Exception ex) {
    						throw new RuntimeException(ex);
    					}
    				} else {
    					conn.set(refreshToAccessKey, auth);
    					conn.set(accessToRefreshKey, refresh);
    				}
    				if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
    					ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;
    					Date expiration = expiringRefreshToken.getExpiration();
    					if (expiration != null) {
    						int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)
    								.intValue();
    						conn.expire(refreshToAccessKey, seconds);
    						conn.expire(accessToRefreshKey, seconds);
    					}
    				}
    			}
    			conn.closePipeline();
    		} finally {
    			conn.close();
    		}
    	}
    

    由此可见并没有在刷新时候保存refresh与refresh_auth两个key。那我们是不是可以重写这个方法?然后把refresh加进去?,我自己有试过:

    /*
    package com.xzb.springcloud.auth.server.config;
    
    import com.xzb.springcloud.common.constant.RedisKeysConstant;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnection;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
    import org.springframework.security.oauth2.common.OAuth2AccessToken;
    import org.springframework.security.oauth2.common.OAuth2RefreshToken;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
    import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
    import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
    import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
    import org.springframework.util.ClassUtils;
    import org.springframework.util.ReflectionUtils;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    
    */
    /**
     * @author zjh
     * @version 1.0
     * @Description token存储
     * @date 2021-01-12 14:49
     *//*
    
     */
    /*@Configuration*/
    
    public class RedisCover extends RedisTokenStore {
        private static final String ACCESS = "access:";
        private static final String AUTH_TO_ACCESS = "auth_to_access:";
        private static final String AUTH = "auth:";
        private static final String REFRESH_AUTH = "refresh_auth:";
        private static final String ACCESS_TO_REFRESH = "access_to_refresh:";
        private static final String REFRESH = "refresh:";
        private static final String REFRESH_TO_ACCESS = "refresh_to_access:";
        private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:";
        private static final String UNAME_TO_ACCESS = "uname_to_access:";
    
        private static final boolean springDataRedis_2_0 = ClassUtils.isPresent(
                "org.springframework.data.redis.connection.RedisStandaloneConfiguration",
                RedisTokenStore.class.getClassLoader());
    
        private final RedisConnectionFactory connectionFactory;
        private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
        private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
    
        private String prefix = RedisKeysConstant.USER_TOKENS;
    
        private Method redisConnectionSet_2_0;
    
        public RedisCover(RedisConnectionFactory connectionFactory) {
            super(connectionFactory);
            this.connectionFactory = connectionFactory;
            if (springDataRedis_2_0) {
                this.loadRedisConnectionMethods_2_0();
            }
        }
    
        @Override
        public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
            this.authenticationKeyGenerator = authenticationKeyGenerator;
        }
    
        @Override
        public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) {
            this.serializationStrategy = serializationStrategy;
        }
    
        @Override
        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }
    
        private void loadRedisConnectionMethods_2_0() {
            this.redisConnectionSet_2_0 = ReflectionUtils.findMethod(
                    RedisConnection.class, "set", byte[].class, byte[].class);
        }
    
        private RedisConnection getConnection() {
            return connectionFactory.getConnection();
        }
    
        private byte[] serialize(Object object) {
            return serializationStrategy.serialize(object);
        }
    
        private byte[] serializeKey(String object) {
            return serialize(prefix + object);
        }
    
        private OAuth2AccessToken deserializeAccessToken(byte[] bytes) {
            return serializationStrategy.deserialize(bytes, OAuth2AccessToken.class);
        }
    
        private OAuth2Authentication deserializeAuthentication(byte[] bytes) {
            return serializationStrategy.deserialize(bytes, OAuth2Authentication.class);
        }
    
        private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) {
            return serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class);
        }
    
        private byte[] serialize(String string) {
            return serializationStrategy.serialize(string);
        }
    
        private String deserializeString(byte[] bytes) {
            return serializationStrategy.deserializeString(bytes);
        }
    
        private static String getApprovalKey(OAuth2Authentication authentication) {
            String userName = authentication.getUserAuthentication() == null ? ""
                    : authentication.getUserAuthentication().getName();
            return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);
        }
    
        private static String getApprovalKey(String clientId, String userName) {
            return clientId + (userName == null ? "" : ":" + userName);
        }
        @Override
        public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
            this.setPrefix(RedisKeysConstant.USER_TOKENS);
            byte[] serializedAccessToken = serialize(token);
            byte[] serializedAuth = serialize(authentication);
            byte[] accessKey = serializeKey(ACCESS + token.getValue());
            byte[] authKey = serializeKey(AUTH + token.getValue());
            byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication));
            byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication));
            byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId());
            RedisConnection conn = getConnection();
            try {
                conn.openPipeline();
                if (springDataRedis_2_0) {
                    try {
                        this.redisConnectionSet_2_0.invoke(conn, accessKey, serializedAccessToken);
                        this.redisConnectionSet_2_0.invoke(conn, authKey, serializedAuth);
                        this.redisConnectionSet_2_0.invoke(conn, authToAccessKey, serializedAccessToken);
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                } else {
                    conn.set(accessKey, serializedAccessToken);
                    conn.set(authKey, serializedAuth);
                    conn.set(authToAccessKey, serializedAccessToken);
                }
                if (!authentication.isClientOnly()) {
                    conn.sAdd(approvalKey, serializedAccessToken);
                }
                conn.sAdd(clientId, serializedAccessToken);
                if (token.getExpiration() != null) {
                    int seconds = token.getExpiresIn();
                    conn.expire(accessKey, seconds);
                    conn.expire(authKey, seconds);
                    conn.expire(authToAccessKey, seconds);
                    conn.expire(clientId, seconds);
                    conn.expire(approvalKey, seconds);
                }
                OAuth2RefreshToken refreshToken = token.getRefreshToken();
                if (refreshToken != null && refreshToken.getValue() != null) {
                    byte[] refresh = serialize(token.getRefreshToken().getValue());
                    byte[] auth = serialize(token.getValue());
                    byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue());
                    byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue());
                    byte[] refreshKey = serializeKey(REFRESH + token.getRefreshToken().getValue());
                    byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + token.getRefreshToken().getValue());
                    if (springDataRedis_2_0) {
                        try {
                            this.redisConnectionSet_2_0.invoke(conn, refreshToAccessKey, auth);
                            this.redisConnectionSet_2_0.invoke(conn, accessToRefreshKey, refresh);
                            this.redisConnectionSet_2_0.invoke(conn, refreshKey, refresh);
                            this.redisConnectionSet_2_0.invoke(conn, refreshAuthKey, refresh);
                        } catch (Exception ex) {
                            throw new RuntimeException(ex);
                        }
                    } else {
                        conn.set(refreshToAccessKey, auth);
                        conn.set(accessToRefreshKey, refresh);
                        conn.set(refreshKey, refresh);
                        conn.set(refreshAuthKey, refresh);
                    }
                    if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
                        ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;
                        Date expiration = expiringRefreshToken.getExpiration();
                        if (expiration != null) {
                            int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)
                                    .intValue();
                            conn.expire(refreshToAccessKey, seconds);
                            conn.expire(accessToRefreshKey, seconds);
                            conn.expire(refreshKey, seconds);
                            conn.expire(refreshAuthKey, seconds);
                        }
                    }
                }
                conn.closePipeline();
            } finally {
                conn.close();
            }
        }
    }
    
    

    这种方式还是存在问题的(1.应该是注入问题重复无设置的prefix;2.就算prefix设置了成功,但是也会导致存储两次,虽然会替换),因为创建时候也会调用。方法不是最好的,舍弃。

    @Override
        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }
    

    3.每次刷新,登录都单独使用accessToken与refreshToken,且旧的保持可用不可以删除,注意这个参数:reuseRefreshToken:注意如下旧的不删除,保持可用:
    refreshAccessToken:

    if (!reuseRefreshToken) {
    			tokenStore.removeRefreshToken(refreshToken);
    			refreshToken = createRefreshToken(authentication);
    		}
    

    这样的话,无论客户端想要延期还是只用旧的都可以支持:
    而且:
    refreshAccessToken()-RedisTokenStore下storeRefreshToken()方法:

    if (!reuseRefreshToken) {
    			tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
    		}
    
    @Override
    	public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
    		byte[] refreshKey = serializeKey(REFRESH + refreshToken.getValue());
    		byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + refreshToken.getValue());
    		byte[] serializedRefreshToken = serialize(refreshToken);
    		RedisConnection conn = getConnection();
    		try {
    			conn.openPipeline();
    			if (springDataRedis_2_0) {
    				try {
    					this.redisConnectionSet_2_0.invoke(conn, refreshKey, serializedRefreshToken);
    					this.redisConnectionSet_2_0.invoke(conn, refreshAuthKey, serialize(authentication));
    				} catch (Exception ex) {
    					throw new RuntimeException(ex);
    				}
    			} else {
    				conn.set(refreshKey, serializedRefreshToken);
    				conn.set(refreshAuthKey, serialize(authentication));
    			}
    			if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
    				ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;
    				Date expiration = expiringRefreshToken.getExpiration();
    				if (expiration != null) {
    					int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)
    							.intValue();
    					conn.expire(refreshKey, seconds);
    					conn.expire(refreshAuthKey, seconds);
    				}
    			}
    			conn.closePipeline();
    		} finally {
    			conn.close();
    		}
    	}
    

    此正好是保存REFRESH、REFRESH_AUTH两个key的:则重写此方法即可:

    package com.xzb.springcloud.auth.server.config;
    
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
    import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
    import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
    import org.springframework.security.oauth2.common.OAuth2AccessToken;
    import org.springframework.security.oauth2.common.OAuth2RefreshToken;
    import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
    import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
    import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.security.oauth2.provider.OAuth2Request;
    import org.springframework.security.oauth2.provider.TokenRequest;
    import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
    import org.springframework.security.oauth2.provider.token.TokenEnhancer;
    import org.springframework.security.oauth2.provider.token.TokenStore;
    import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.Date;
    import java.util.Set;
    import java.util.UUID;
    
    /**
     * @author zjh
     * @version 1.0
     * @Description 刷新token自定义重新新增一个token
     * @date 2021-01-12 16:12
     */
    public class DefaultServiceCover extends DefaultTokenServices {
    
        private boolean supportRefreshToken = true;
    
        private boolean reuseRefreshToken = true;
    
        private TokenStore tokenStore;
    
        private TokenEnhancer accessTokenEnhancer;
    
        private AuthenticationManager authenticationManager;
    
        public DefaultServiceCover(TokenStore tokenStore, Boolean supportRefreshToken, Boolean reuseRefreshToken,
                                   TokenEnhancer accessTokenEnhancer) {
            this.tokenStore = tokenStore;
            this.supportRefreshToken = supportRefreshToken;
            this.reuseRefreshToken = reuseRefreshToken;
            this.accessTokenEnhancer = accessTokenEnhancer;
        }
    
        @Override
        @Transactional(noRollbackFor = {InvalidTokenException.class, InvalidGrantException.class})
        public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)
                throws AuthenticationException {
    
            if (!supportRefreshToken) {
                throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
            }
    
            OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
            if (refreshToken == null) {
                throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
            }
    
            OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken);
            if (this.authenticationManager != null && !authentication.isClientOnly()) {
                // The client has already been authenticated, but the user authentication might be old now, so give it a
                // chance to re-authenticate.
                Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities());
                user = authenticationManager.authenticate(user);
                Object details = authentication.getDetails();
                authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user);
                authentication.setDetails(details);
            }
            String clientId = authentication.getOAuth2Request().getClientId();
            if (clientId == null || !clientId.equals(tokenRequest.getClientId())) {
                throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue);
            }
    
            // clear out any access tokens already associated with the refresh
            // token.
            tokenStore.removeAccessTokenUsingRefreshToken(refreshToken);
    
            if (isExpired(refreshToken)) {
                tokenStore.removeRefreshToken(refreshToken);
                throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken);
            }
    
            authentication = createRefreshedAuthentication(authentication, tokenRequest);
    
            if (!reuseRefreshToken) {
                tokenStore.removeRefreshToken(refreshToken);
                refreshToken = createRefreshToken(authentication);
            }
    
            OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
            tokenStore.storeAccessToken(accessToken, authentication);
            tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
            return accessToken;
        }
    
        private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) {
            OAuth2Authentication narrowed = authentication;
            Set<String> scope = request.getScope();
            OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request);
            if (scope != null && !scope.isEmpty()) {
                Set<String> originalScope = clientAuth.getScope();
                if (originalScope == null || !originalScope.containsAll(scope)) {
                    throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope
                            + ".", originalScope);
                } else {
                    clientAuth = clientAuth.narrowScope(scope);
                }
            }
            narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication());
            return narrowed;
        }
    
        private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
            if (!isSupportRefreshToken(authentication.getOAuth2Request())) {
                return null;
            }
            int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
            String value = UUID.randomUUID().toString();
            if (validitySeconds > 0) {
                return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis()
                        + (validitySeconds * 1000L)));
            }
            return new DefaultOAuth2RefreshToken(value);
        }
    
        private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
            DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
            int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
            if (validitySeconds > 0) {
                token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
            }
            token.setRefreshToken(refreshToken);
            token.setScope(authentication.getOAuth2Request().getScope());
    
            return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
        }
    
    }
    
    

    改后的**AuthorizationServerConfig(extends AuthorizationServerConfigurerAdapter)**中:

    @Bean
        public DefaultTokenServices tokenService() {
            // 通过TokenEnhancerChain增强器链将jwtAccessTokenConverter(转换成jwt)和jwtTokenEnhancer(往里面加内容加信息)连起来
            TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
            List<TokenEnhancer> enhancerList = new ArrayList<>();
            enhancerList.add(jwtAccessTokenConverter);
            enhancerChain.setTokenEnhancers(enhancerList);
            DefaultServiceCover tokenServices = new DefaultServiceCover(redisTokenStore(), true,
                    true, enhancerChain);
            // 配置token存储
            tokenServices.setTokenStore(redisTokenStore());
            // 开启支持refresh_token,此处如果之前没有配置,启动服务后再配置重启服务,可能会导致不返回token的问题,解决方式:清除redis对应token存储
            tokenServices.setSupportRefreshToken(true);
            // 复用refresh_token
            tokenServices.setReuseRefreshToken(true);
            // token有效期,设置2小时
            tokenServices.setAccessTokenValiditySeconds(2 * 60 * 60);
            // refresh_token有效期,设置一周
            tokenServices.setRefreshTokenValiditySeconds(15 * 24 * 60 * 60);
            tokenServices.setTokenEnhancer(enhancerChain);
            return tokenServices;
        }
    

    问题得到解决

    转载注明出处。

    展开全文
  • Python: Invalid Token

    千次阅读 2020-12-06 01:16:57
    And I get this error: File "D:\development\Python\ProjectEuler\p11.py", line 3 [ 08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91 , 08 ], ^ SyntaxError: invalid token Why is ...

    Some of you may recognize this as Project Euler's problem number 11. The one with the grid.

    I'm trying to replicate the grid in a large multidimensional array, But it's giving me a syntax error and i'm not sure why

    grid = [

    [ 08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 08 ],

    [ 49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00 ],

    [ 81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65 ],

    ...

    And I get this error:

    File "D:\development\Python\ProjectEuler\p11.py", line 3

    [ 08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91 , 08 ],

    ^ SyntaxError: invalid token

    Why is it throwing an error before the comma?

    展开全文
  • python invalid token

    千次阅读 2019-03-01 10:58:07
    sql = ''' year=%d and month=5d''' %(2019,03) 结果报invalid token 原因如下: 解决: 原文地址:https://stackoverflow.com/questions/36386346/syntaxerror-invalid-token
  • 添加用户可以很好地工作,但是当我试图解密密码时,会出现cryptography.fernet.InvalidToken错误,所以问题应该出在密钥上,尽管我看不出我在这里做错了什么。代码段:def generate_master_key():m...
  • 因为struts2阻塞tokenSession的id值相同的访问,...按理说使用tokenSession可以不配置invalid.token的result,但是偶尔有种情况会提示“No result defined for action com.syq2cy.test.LoginAction and result in...
  • 成功解决 SyntaxError: invalid token

    万次阅读 多人点赞 2018-05-26 15:32:30
    成功解决 SyntaxError: invalid token 目录 解决问题 解决思路 解决方法 解决问题 SyntaxError: invalid token 解决思路 语法错误:标记无效 解决方法 语法错误:无效令牌,故导入...
  • Dubbo invalid token

    2019-09-25 13:45:52
    Internal server error: Invalid token! Forbid invoke remote service interface com.biz.service.rest.RestServicemethod back() from consumer 0:0:0:0:0:0:0:1 to provider 172.24.82.37   是因为dubbo的...
  • 1. 问题前面几篇博客 spring security在集成...但是在使用 postman 进行调用的时候出现这个问题HTTP Status 403-Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.然
  • 获取到token后调用服务都正常,但是如果服务之间通过feign互相调用, 就会出现token不正确的问题,生产者一方会出现如下警告: WARN 22880 --- [nio-8200-exec-2] o.s.b.a.s.o.r.UserInfoTokenServices : Could ...
  • "errmsg": "invalid credential, access_token is invalid or not latest rid: 6004f3da-1529ba72-5c345f67" } 报错原因 access_token 过期!需要刷新 access_token! 《获取 access_token》 getAccessToken ...
  • 这是因为需要申请token。 申请页面为:https://cesium.com/ion/tokens 在初始化viewer之前,将token加入即可 Cesium.Ion.defaultAccessToken='你的token'; var viewer = new Cesium.Viewer('cesiumContainer',{ ...
  • 这是因为需要申请token。 申请页面为:https://cesium.com/ion/tokens 在初始化viewer之前,将token加入即可 Cesium.Ion.defaultAccessToken='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMjJjMzI5YS1...
  • {“responseCode”:“6”,“responseMessage”:“Token is expired or invalid”} 问题定位 联系华为官方技术客服(地址:https://developer.huawei.com/consumer/cn/support/feedback/#/)沟通定位了下,建议从以下...
  • 微信access_token分为两种,一种是网页授权access_token,一种是全局接口调用凭证。有关这两个区别,可以查看微信网页授权access_token和普通access_token区别。今天主要来说获取全局接口调用凭证access_token的坑,...
  • Invalid or unexpected token --> 无效或意外的 var left = [1,2,3],right = [1,2,3] if(left[1] > right[0]){ left.splice(1,1) right.splice(0,1) } 运行这样一段代码,就会报错。 翻译成中文是: 捕获...
  • 问题:“INVALIDis not a valid start token 报错的配置文件 - job_name: 'jiankong' scrape_interval: 15s static_configs: - targets: ['192.168.17.54:6666'] 解决方法: 添加一行代码 metrics_path: '/...
  • 网站微信公众平台老是报错 {"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [70D7Ma0416vr70!]"} ,应该是access_token过期了,但直接用浏览器访问$url=...
  • 这个大部分原因是access_token不正确导致的。这个access_token是微信开放文档---公众号---开始开发---获取Access Token下的获取access_token获取的。而不是下面的微信网页开发---网页授权中获取access_token。 ...
  • 文件上传csrftoken获取不到 <!DOCTYPE html><html><head><title>Apache Tomcat/8.5.6 - Error report</title><style type="text/css">H1 {font-family:Tahoma,Arial,sans-...
  • 严重: Servlet.service() for servlet [SpringMVC] in context with path [/] threw exception [Request processing failed; nested exception is java.lang....
  • 40001: invalid credential, access_token is invalid or not latest rid: 5fdb2087-1f36ab8e-5c34337a 因为AppSecret之前一直使用, 所以不会错误,所以只能是access_token失效。 百思不得其解,为啥有时候能成功
  • 在表单中添加隐藏域 Spring Security默认启用CSRF 防御 官方原文: ...When should you use CSRF ... Our recommendation is to use CSRF protection for any request that could be processed by a browser by
  • JWT token无效invalid signature

    千次阅读 2019-08-20 08:55:27
    invalid signature 我的user模型是这样的 后面看https://www.jianshu.com/p/f0a55f39dfa8链接说,jwt生成token时默认是需要用到username,并且username需要保证唯一,或者重写UserManager的get_by_natura....
  • nested exception is org.springframework.http.InvalidMediaTypeException: Invalid mime type "application/json, application/json": Invalid token character ',' in token "json, application/json"] with ...
  • 前端出现401 token invalid(令牌无效)

    千次阅读 2020-07-25 14:39:24
    后端控制台显示 token invalid(令牌无效),经过长时间的查找,终于解决了,如下: //为了方便,写的简陋一点,希望有所帮助(我也是这么过来的:哭泣) var jwt = (jwt就是从后端获取到的token); function ...
  • 今天在做一个扫描微信公众号带参数二维码的时候我首先通过:"...; 获取access_token"... 获取 用户信息但是在获取用户信息的时候出现了 invalid credential, access_token is invalid or no...
  • 微信模板消息报:40001:invalid credential, access_token is invalid or not latest。 大意是access_token无效或者不是最新的, 于是想到access_token每次从微信服务器取一次就新生成一次,同时老的token就失效了。...
  • jwts := jwt.NewWithClaims(jwt.SigningMethodES256, c) // SigningMethodES256 *SigningMethodECDSA 此类型会报错: key is of invalid type` jwts := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // S

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,535
精华内容 9,814
关键字:

invalidistoken