简单说下,项目是springcloud架构,用的spring security oauth2

就是如果token过期了或者token错误了,请求开放的接口是会被看拦截的,但是不带token就能请求。有一种解决方案是在请求判断这个地址是不是免登陆的是的话把请求头的token给去掉,这种方法也可以做到,但是如果是登录用户的话在有必要获取到访问用户的时候就没方法拿到用户了,虽然这种情况比较少。

解决方案:重写原本的认证管理器

import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;

import java.util.UUID;

/**
 * 认证管理器
 * 继承于原本的OAuth2认证管理器,替代原本的认证管理器
 * 目的是做到如果原来的认证管理器如果提取token并认证失败报错的话,提供一个匿名的访问认证 {@link AnonymousAuthenticationToken}
 * 最终效果是实现即时请求 无须认证 的接口时带着 过期 或 无效 的 token 时,可以正常继续请求而不会因为 过期或无效的token 导致请求失败
 */
public class MyOAuth2AuthenticationManager extends OAuth2AuthenticationManager {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            return super.authenticate(authentication);
        } catch (AuthenticationException | InvalidTokenException e) {
            return new AnonymousAuthenticationToken(UUID.randomUUID().toString(), "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
        }
    }
}

 再去吧认账管理器添加上

import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        //添加认证管理器
        resources.authenticationManager(new MyOAuth2AuthenticationManager());
    }

}

原理也比较简单,原本的认证管理器如果对携带的token认证失败会报错,然后调用认证管理器的filter捕获到报错后进行一个token失效的处理,就是进行一系列的通知返回什么的。

这里继承原本的认证管理器并注册替换掉它,在调用认证方法时调用父类的认证方法(也就是原本的认证方法),然后做认证失败异常捕获,捕获到异常直接返回一个匿名用户的认证。

目前测试是如果接口没有使用 permitAll 的话 匿名用户 是没法请求到接口的。

通过源码看到如果是没有带token请求的话 security 也是创建了一个匿名用户的认证。所以应该没什么问题。如果有什么问题的话务必告知与我

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐