java - 如何在 oauth2 app spring boot 中正确设置用户角色
问题描述
在我的应用程序中实现 oauth2 后,我正在努力解决 Spring Security 问题。这是我的第一次体验,但很高兴听到好的或愤怒的评论。这就是改进的方法。
问题:
在我的应用程序登录期间,我看到我从 DefaultOidcUser 类的 google oidcuser 对象中检索。authorities
这个对象有4 个项目的集合:
老实说,我不明白为什么我在我的系统中为这个用户获得 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 会将范围和默认 USER 角色映射到 OidcUser 对象上授予的权限。您只需在您的 CustomOidcUser 中返回它
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return oidcUser.getAuthorities();
}
您需要在您的 CustomOidcUser 对象中创建一个自定义的 GrantedAuthorities 集合,然后您的 CustomOidcUserService 您需要手动将数据库中的角色添加到此集合中。
Collection<GrantedAuthority> authorities ....
authorities.add(new SimpleGrantedAuthority("ROLE_...."));
推荐阅读
- php - 如何在 eloquent withCount 函数回调中获取枢轴数据?
- bash - Bash:从字符串中获取 3 个元素
- azure-cosmosdb - CosmosDB,很长的索引,也是分区键
- python - Python中自定义类的字符串格式
- javascript - JS onClick变换旋转问题水平垂直
- oracle - Oracle - 两列上的间隙和孤岛
- google-apps-script-addon - 如何在附加组件商店中显示我的附加组件?
- ssas - 在 MDX 中计算累积月份值
- reactjs - 为 Ant Design 验证器 (ReactJS) 实现可重用的方法
- html - index.html 中的 CDN 链接给出错误