java - 如何在 REST API 中获取登录用户 ID

标签 java rest authentication spring-security

我已经使用 REST API 约定构建了一个 Java 应用程序。我正在研究端点,仅当对象通过数据库中的通用 ID(ManyToOne 注释)与用户连接时才返回对象。为了实现这一点,我需要当前登录的用户 ID 来将其与对象的用户 ID 进行比较。如果 Id 相同,则端点返回数据。我知道解决方案为“主体”或“身份验证”类,但它们提供了除“id”之外的所有内容。我使用 spring security http basic 进行身份验证。 我的身份验证类:


@Component
public class CustomAuthenticator implements AuthenticationProvider {

    private final UserRepository userRepository;

    private final PasswordEncoder passwordEncoder;

    @Autowired
    public CustomAuthenticator(UserRepository userRepository, @Lazy PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        String login = authentication.getName();
        String password = authentication.getCredentials().toString();

        User user = userRepository.findByLogin(login).orElseThrow(() -> new EntityNotFoundException("User not found"));
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new BadCredentialsException("Bad credentials");
        }

        return new UsernamePasswordAuthenticationToken(login, password, convertAuthorities(user.getRoles()));

    }

    private Set<GrantedAuthority> convertAuthorities(Set<UserRole> userRoles) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        for (UserRole ur : userRoles) {
            authorities.add(new SimpleGrantedAuthority(ur.getRole().toString()));
        }
        return authorities;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

安全配置类:


@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CustomAuthenticator customAuthenticator;

    public SecurityConfig(CustomAuthenticator customAuthenticator) {
        this.customAuthenticator = customAuthenticator;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        return passwordEncoder;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/api").permitAll()
                .antMatchers("/api/register").permitAll()
                //TODO everybody now has access to database, change it later
                .antMatchers("/h2-console/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic();

        http
                .csrf().disable()
                .headers().frameOptions().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticator);
    }
}

有人知道如何解决这个问题吗?

最佳答案

您可以使用UserDetails类并为username字段设置id,该类由spring security提供。

如果您不想要该解决方案,您可以创建一个子类扩展UserDetails类并决定一个id字段。收到请求时,将principal解析为UserDetailssubclass extends UserDetails以获取id

例如:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userPrincipal = (UserDetails)authentication.getPrincipal();

关于java - 如何在 REST API 中获取登录用户 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61452272/

相关文章:

java - 使用类添加 View 的预期类或包

java - 温度打印至小数点后一位的格式

java google app引擎从字符串查询(如Python的GQL)

java - Android Libgdx Assets 管理器 : asset not loaded

api - 对于 HTTP POST 使用 URI 路径变量怎么样?

python - 如何将一个字段显示为序列化器中的字符串?

django - 使用 Django REST Framework 的 SAML SSO 身份验证

web-services - REST API - 如果请求正文的信息超出需要,我是否应该返回错误?

android - 从 Android 应用程序登录网页

iphone - 游戏中心无法识别该游戏