如何在oauth2 app spring Boot 中正确设置用户角色

pgx2nnw8  于 2023-04-11  发布在  Spring
关注(0)|答案(2)|浏览(191)

在我的应用程序中实现oauth2后,我一直在努力解决Spring Security 问题。这是我的第一次经历,但我很高兴听到好的或愤怒的评论。这是改进的方法。

**问题:**在我的应用程序中登录时,我看到我从谷歌检索DefaultOidcUser类的oidcuser对象。该对象具有authorities的集合,其中包含4项:

老实说,我不明白为什么我在我的系统中为这个用户获取ROLE_USER,因为实际上它在我的系统中有ADMIN角色(角色是由我创建的)。
我在App中有三个角色:用户、管理员、管理员。但不知道如何正确设置特殊用户的特定角色。
正因为如此,当我把smth写成:

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

我得到403 cos,因为我理解我为每个用户得到ROLE_USER。
你能帮我设置每个用户的角色,但从我的数据库(不是这个默认的ROLSER_USER从谷歌)?我也读了有关GrantedAuthorities和grantedAuthorities的Map器,但它对我来说有点不清楚。
我会很高兴听到任何意见.任何有用的链接,以提高我对这方面的知识. 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();
  }
qxsslcnc

qxsslcnc1#

对于OIDC,默认情况下Spring会将作用域和默认的USER角色Map到OidcUser对象上的授权机构。

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

您需要在CustomOidcUser对象中创建一个自定义的GrantedAuthorities集合,然后在CustomOidcUserService中手动将数据库中的角色添加到此集合。

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

mkh04yzy2#

对我来说,下面的代码工作,它类似于Lesniak的答案,但不一样。

@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest)
            throws OAuth2AuthenticationException {
        OAuth2User user = super.loadUser(userRequest);
        return new CustomOAuth2User(user);
    }
}

下面显示了CustomOAuth2User类:

@AllArgsConstructor
public class CustomOAuth2User implements OAuth2User {

    private OAuth2User oAuth2User;

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

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        oAuth2User.getAuthorities().forEach(ga -> authorities.add(ga));
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        return authorities;
    }

    @Override
    public String getName() {
        return oAuth2User.getAttribute("name");
    }

    public String getEmail() {
        return oAuth2User.<String>getAttribute("email");
    }
}

相关问题