gpt4 book ai didi

java - 如何保存使用 OAuth 2 (Spring) 登录的用户?

转载 作者:搜寻专家 更新时间:2023-11-01 00:54:23 25 4
gpt4 key购买 nike

我的主要目标是存储每个用户的客户端 ID,一旦他们使用谷歌登录。这github repo包含我到目前为止所需的大部分内容。关注的两个主要文件是OAuthSecurityConfig.javaUserRestController.java .

当我导航到 /user 时,Principal 包含我需要的有关用户的所有详细信息。因此,我可以使用以下代码片段来获取我需要的数据:

Authentication a = SecurityContextHolder.getContext().getAuthentication();
String clientId = ((OAuth2Authentication) a).getOAuth2Request().getClientId();

然后我可以将 clientId 存储在一个 repo 中

User user = new User(clientId);
userRepository.save(user);

问题是用户不必导航到 /user。因此,无需注册即可导航到 /score/user1

此 API 旨在成为 future android 应用程序的后端,因此重定向到 /user 的 jquery 将不安全且无法工作。


我尝试过的事情:

尝试 1

我创建了以下类:

@Service
public class CustomUserDetailsService implements UserDetailsService {

private final UserRepository userRepository;

@Autowired
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(String.format("User %s does not exist!", username));
}
return new UserRepositoryUserDetails(user);
}
}

并覆盖WebSecurityConfigurerAdapter:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}

当用户登录时,两个重写的方法都不会被调用(我用 System.out.println 检查过)


尝试 2

我尝试添加 .userDetailsS​​ervice(customUserDetailsS​​ervice)

到:

@Override
protected void configure(HttpSecurity http) throws Exception {

http
// Starts authorizing configurations.
.authorizeRequests()
// Do not require auth for the "/" and "/index.html" URLs
.antMatchers("/", "/**.html", "/**.js").permitAll()
// Authenticate all remaining URLs.
.anyRequest().fullyAuthenticated()
.and()
.userDetailsService(customUserDetailsService)
// Setting the logout URL "/logout" - default logout URL.
.logout()
// After successful logout the application will redirect to "/" path.
.logoutSuccessUrl("/")
.permitAll()
.and()
// Setting the filter for the URL "/google/login".
.addFilterAt(filter(), BasicAuthenticationFilter.class)
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

这两种方法都没有被调用,我觉得我离解决方案还差得很远。任何帮助将不胜感激。

最佳答案

这里的方法是提供一个自定义的 OidcUserService 并覆盖 loadUser() 方法,因为 Google 登录是基于 OpenId Connect 的。

首先定义一个模型类来保存提取的数据,像这样:

public class GoogleUserInfo {

private Map<String, Object> attributes;

public GoogleUserInfo(Map<String, Object> attributes) {
this.attributes = attributes;
}

public String getId() {
return (String) attributes.get("sub");
}

public String getName() {
return (String) attributes.get("name");
}

public String getEmail() {
return (String) attributes.get("email");
}
}

然后使用 loadUser() 方法创建自定义 OidcUserService,该方法首先调用提供的框架实现,然后添加您自己的逻辑来保存您需要的用户数据,如下所示:

@Service
public class CustomOidcUserService extends OidcUserService {

@Autowired
private UserRepository userRepository;

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

try {
return processOidcUser(userRequest, oidcUser);
} catch (Exception ex) {
throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause());
}
}

private OidcUser processOidcUser(OidcUserRequest userRequest, OidcUser oidcUser) {
GoogleUserInfo googleUserInfo = new GoogleUserInfo(oidcUser.getAttributes());

// see what other data from userRequest or oidcUser you need

Optional<User> userOptional = userRepository.findByEmail(googleUserInfo.getEmail());
if (!userOptional.isPresent()) {
User user = new User();
user.setEmail(googleUserInfo.getEmail());
user.setName(googleUserInfo.getName());

// set other needed data

userRepository.save(user);
}

return oidcUser;
}
}

并在安全配置类中注册自定义的OidcUserService:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private CustomOidcUserService customOidcUserService;

@Override
public void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(customOidcUserService);
}
}

模式详细解释可以在文档中找到:

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2login-advanced-oidc-user-service

关于java - 如何保存使用 OAuth 2 (Spring) 登录的用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48598417/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com