簡體   English   中英

如何在 oauth2 應用程序 spring 引導中正確設置用戶角色

[英]How to correctly set role for User in oauth2 app spring boot

在我的應用程序中實施 oauth2 后,我正在努力解決 spring 安全問題。 這是我的第一次體驗,但很高興聽到好的或憤怒的評論。 這就是改進的方法。

問題:在我的應用程序登錄期間,我看到我從 DefaultOidcUser class 的 google oidcuser object 檢索。 此 object 具有 4 項authorities集合: 在此處輸入圖像描述

老實說,我不明白為什么我在我的系統中為這個用戶獲得 ROLE_USER,因為它實際上在我的系統中具有 ADMIN 角色(角色是由我創建的)。

一般來說,我的應用程序中有 3 個角色:用戶、經理、管理員。 但無法理解如何為特殊用戶正確設置特定角色。

正因為如此,當我把 smth 像:

  .antMatchers("/api/**").hasRole(Role.ADMIN.name())
  .antMatchers("/administration/**").hasRole(Role.ADMIN.name())

據我了解,我得到了 403 cos,我為每個用戶得到了 ROLE_USER。

你能幫我為每個用戶設置角色,但從我的數據庫(不是谷歌的這個默認 ROLSER_USER)? 我還閱讀了有關 GrantedAuthorities 和 grantAuthorities 的映射器的信息,但對我來說有點不清楚。

我很高興聽到任何意見。 任何有用的鏈接來提高我對此的了解。 Cos 的主要目標:了解它是如何工作的。

下面是我的 oauth2 實現的其他類:

@Getter
@Setter
@RequiredArgsConstructor
public class CustomOidcUser implements OidcUser {

    private final OidcUser oidcUser;
    private String email;
    private String firstName;
    private String lastName;

    @Override
    public Map<String, Object> getClaims() {
        return oidcUser.getClaims();
    }
    @Override
    public OidcUserInfo getUserInfo() {
        return oidcUser.getUserInfo();
    }

    @Override
    public OidcIdToken getIdToken() {
        return oidcUser.getIdToken();
    }

    @Override
    public Map<String, Object> getAttributes() {
        return oidcUser.getAttributes();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return oidcUser.getAuthorities();
    }

    @Override
    public String getName() {
        return oidcUser.getName();
    }

}
@Service
@RequiredArgsConstructor
public class CustomOidcUserService extends OidcUserService {

    private final UserRepository repository;
    private static final String GOOGLE_KEY_LASTNAME = "family_name";
    private static final String GOOGLE_KEY_FIRSTNAME = "given_name";

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        final OidcUser oidcUser = super.loadUser(userRequest);
        CustomOidcUser newUser =  new CustomOidcUser(oidcUser);

        String email = oidcUser.getAttributes().get("email").toString();
        User user = createUserIfNoExist(email, oidcUser);
        newUser.setEmail(email);
        newUser.setFirstName(user.getFirstName());
        newUser.setLastName(user.getLastName());

        return newUser;
    }

    public User createUserIfNoExist(String email, OidcUser oidcUser) {
        return repository.findByEmail(email)
                .orElseGet(() -> {
                    User newUser = new User();
                    newUser.setEmail(email);
                    newUser.setRole(Role.USER);
                    newUser.setStartWorkAt(LocalDate.now());
                    newUser.setLastLoginDate(LocalDateTime.now());
    ...

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  private final AuthProvider authProvider;
  private final OnSuccessHandler onSuccessHandler;
  private final CustomOidcUserService customOidcUserService;
  private final UserService userService;

  protected void configure(HttpSecurity http) throws Exception {
    SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
    successHandler.setUseReferer(true);
    successHandler.setDefaultTargetUrl("/success");
    successHandler.setAlwaysUseDefaultTargetUrl(true);

    http
        .addFilterAfter(new UserHasManagerFilter(userService), BasicAuthenticationFilter.class)
        .cors()
        .and()
          .csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/api/**").hasRole(Role.ADMIN.name())
          .antMatchers("/administration/**").hasRole(Role.ADMIN.name())
        .and()
            .httpBasic()
        .and()
          .formLogin()
          .loginPage("/unauthorized")
          .loginProcessingUrl("/login")
          .defaultSuccessUrl("/success")
          .failureUrl("/failed")
          .successHandler(successHandler)
          .usernameParameter("email")
          .passwordParameter("password")
          .permitAll()
        .and()
          .logout()
          .logoutUrl("/logout")
          .logoutSuccessUrl("/logout_success")
          .permitAll()
        .and()
            .oauth2Login()

              .loginPage("/")
              .userInfoEndpoint(userInfoEndpoint ->
                      userInfoEndpoint.oidcUserService(customOidcUserService)
                      .customUserType(CustomOidcUser.class, "google")
//                      .userAuthoritiesMapper(userAuthoritiesMapper())
              )

              .defaultSuccessUrl("/dashboard", true)
              .successHandler(onSuccessHandler)
              .failureHandler(authenticationFailureHandler())
            .permitAll()
        .and()
        .authorizeRequests()
        .antMatchers("/**")
        .permitAll();
  }

對於 OIDC,默認情況下 Spring 將 map 范圍和默認 USER 角色授予 OidcUser object 上的授權。 您只需在您的 CustomOidcUser 中返回它

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return oidcUser.getAuthorities();
}

您需要在您的 CustomOidcUser object 中創建一個自定義的 GrantedAuthorities 集合,然后您的 CustomOidcUserService 您需要手動將數據庫中的角色添加到此集合中。

Collection<GrantedAuthority> authorities ....
authorities.add(new SimpleGrantedAuthority("ROLE_...."));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM