在控制器方法调用之前将oauth2用户属性Map到对象

pxq42qpu  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(267)

我目前拥有的

我目前正在为我的公司实施一个oidc资源提供商。他们使用InternoidC服务器,我通过以下示例成功地使用了它:https://github.com/jgrandja/oauth2login-demo/tree/linkedin
我现在可以从授权服务器检索用户信息,如下所示:

@RestController
@RequestMapping("/some/route")
public class SomeController {

    @GetMapping("/some/route")
    public ResponseEntity<?> getSomething(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) {
        String userInfoEndpointUri = authorizedClient.getClientRegistration()
                .getProviderDetails().getUserInfoEndpoint().getUri();
        Map userAttributes = this.webClient
                .get()
                .uri(userInfoEndpointUri)
                .attributes(oauth2AuthorizedClient(authorizedClient))
                .retrieve()
                .bodyToMono(Map.class)
                .block();
        String firstName = (String) userAttributes.get("first_name");
        String lastName = (String) userAttributes.get("last_name");
        ...
    }

}

我想要什么

我现在正在寻找一个解决方案来Map userAttributes 调用控制器方法之前的对象,以便获得例如:

@GetMapping("/some/route")
public ResponseEntity<?> getSomething(MyCostumUserBean user) {
    String firstName = user.getFirstName();
    String lastName = user.getLastName();
    ...
}

我读到了一些关于 ChannelInterceptorHandlerInterceptor 还有 PrincipalExtractorAuthoritiesExtractor . 问题是,我只是在学习spring框架,这些可能性让我无法承受。
如果该方法允许一些验证,并且在验证失败时会立即响应错误代码,那将是一个加号。
在实现这一点之后,我想补充以下信息: MyCostumUserBean 从另一台服务器发送当前会话用户的身份,并接收该用户的角色/权限等信息。
我试着把它放在一张照片里:

问题:

spring框架打算用什么方法来处理这个问题?我如何做到这一点?
额外:依靠它安全吗 OAuth2AuthorizedClient.getPrincipalName() ? 或者,用户可以通过伪造cookie/token来伪造吗?

vcudknz3

vcudknz31#

我想您是在询问如何配置成功处理程序,或者是一个可以检查用户属性的过滤器。
如果这就是你要问的,有很多方法可以做到。例如:
使用用户范围检查:(需要提前将范围分配给用户。)

@ResponseBody
@GetMapping("/some/route")
    public String getSomeThing(@RegisteredOAuth2AuthorizedClient("custom") OAuth2AuthorizedClient authorizedClient) {
        Set<String> scopes = authorizedClient.getAccessToken()
            .getScopes();
        if (scopes.contains("users:read")) {
         } else if (scopes.contains("users:read")) {
            return " page 1";
        } else {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Forbidden.");
        }
    }

您可以在successhandler中放入一些逻辑:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/**")
        .permitAll().and()
        .formLogin()
        .successHandler(successHandler());
}

@Bean
public CustomSuccessHandler successHandler() {
    return new CustomSuccessHandler();
}

如果您想为您的安全配置应用过滤器:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            ...
            .and() 
            .addFilterBefore(getBeforeAuthenticationFilter(), CustomBeforeAuthenticationFilter.class)
            .formLogin()
                .loginPage()
                .permitAll()
            ...
    }

    public UsernamePasswordAuthenticationFilter getBeforeAuthenticationFilter() throws Exception {
        CustomBeforeAuthenticationFilter filter = new CustomBeforeAuthenticationFilter();
....
        return filter;
    }

}

您还可以通过使用自定义过滤器链,通过在其中指定不同的顺序和相对登录名,来实现相同的目的。

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapterForUserGroup1 extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {

     ...;
  }
}

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapterForUserGroup2 extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {

     ...;
  }
}

相关问题