oauth2 绕过登录认证即可调取接口

问题描述:

最近公司想开发官网,之前的项目使用oauth2,所有接口都需要登录认证。官网接口空顶无法登录后再调取,所以想开放某些接口用于首页直接使用。

解决方案:

之前的解决方案是在ResourceServerConfig类中configure方法中对部分接口开放,

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore jwtTokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resource) throws Exception {
        resource.resourceId("app").tokenStore(jwtTokenStore);
        OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        authenticationEntryPoint.setExceptionTranslator(new CustomExceptionTranslator());
        resource.authenticationEntryPoint(authenticationEntryPoint);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().antMatchers("/file/**").permitAll().and()
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and()
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

之前关键是在这行代码authorizeRequests().antMatchers("/file/**").permitAll(),在antMatchers中添加要开放的接口地址。之前使用shiro,可以通过注解方式自定义控制接口无需认证访问的解决,我这次也想这样做。
1.先定义一个注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthIgnore {
    boolean required() default true;
}

2.编写配置类

@Configurable
@Component
@ConfigurationProperties(prefix = "security.oauth2.client.ignore-urls")
public class AuthIgnoreConfig implements InitializingBean {

    @Autowired
    private WebApplicationContext applicationContext;

    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
    private static final String ASTERISK = "*";

    @Getter
    @Setter
    private List<String> ignoreUrls = new ArrayList<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

        map.keySet().forEach(mappingInfo -> {
            HandlerMethod handlerMethod = map.get(mappingInfo);
            AuthIgnore method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), AuthIgnore.class);
            Optional.ofNullable(method)
                    .ifPresent(authIgnore -> mappingInfo
                            .getPatternsCondition()
                            .getPatterns()
                            .forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, ASTERISK))));
            AuthIgnore controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), AuthIgnore.class);
            Optional.ofNullable(controller)
                    .ifPresent(authIgnore -> mappingInfo
                            .getPatternsCondition()
                            .getPatterns()
                            .forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, ASTERISK))));
        });
    }
}

3.简单修改ResourceServerConfig类

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore jwtTokenStore;
    private final AuthIgnoreConfig authIgnoreConfig;

    public ResourceServerConfig(AuthIgnoreConfig authIgnoreConfig) {
        this.authIgnoreConfig = authIgnoreConfig;
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resource) throws Exception {
        resource.resourceId("app").tokenStore(jwtTokenStore);
        OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        authenticationEntryPoint.setExceptionTranslator(new CustomExceptionTranslator());
        resource.authenticationEntryPoint(authenticationEntryPoint);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
    	String[] urls = authIgnoreConfig.getIgnoreUrls().stream().distinct().toArray(String[]::new);
        http
            .csrf().disable()
            .authorizeRequests().antMatchers("/file/**").permitAll()
            .and().authorizeRequests().antMatchers(urls).permitAll()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and()
            .authorizeRequests()
            .anyRequest().authenticated();
    }
}

4.在方法Controller或者接口上添加注解@AuthIgnore即可实现

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OAuth2是一种授权机制,它允许第三方应用程序通过访问令牌来访问用户数据。OAuth2标准定义了四个角色:资源拥有者、客户端、授权服务器和资源服务器。其中,客户端是需要访问用户数据的第三方应用程序,授权服务器是负责验证用户身份并颁发访问令牌的服务器,资源服务器是存储用户数据的服务器。 在OAuth2的标准流程中,用户首先向客户端提供其凭据,客户端将这些凭据发送到授权服务器进行验证。如果验证成功,授权服务器将颁发一个访问令牌给客户端,客户端使用这个令牌来访问资源服务器的受保护资源。 但是,在某些情况下,第三方应用程序可能需要使用自己的登录系统来验证用户身份,而不是使用授权服务器的登录系统。在这种情况下,可以使用自定义登录接口来实现。 自定义登录接口的基本流程如下: 1. 用户向客户端提供凭据(例如用户名和密码)。 2. 客户端将这些凭据发送到自定义登录接口进行验证。 3. 如果验证成功,自定义登录接口将颁发一个访问令牌给客户端。 4. 客户端使用这个令牌来访问资源服务器的受保护资源。 需要注意的是,自定义登录接口必须与授权服务器的登录系统进行集成,以确保用户身份验证的安全性和正确性。 总之,自定义登录接口可以为第三方应用程序提供更大的灵活性和自主性,使其能够更好地适应不同的应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值