java - spring security 从数据库中获取用户 ID

标签 java spring spring-mvc authentication spring-security

我正在使用 spring security 进行身份验证并成功获得 User在我需要的任何地方对象 ( org.springframework.security.core.userdetails.User)。

但我想要UserId另外, Spring 的 User 中没有目的。所以我创建了自己的对象(com.app.site.pojo.User)。它有一些额外的变量,例如 userIduser date of birth 等。现在我希望 spring security 使用我的 user对象而不是 Spring User目的。它应该包含有关该用户的所有详细信息。

我试图将用户对象类型转换为我的对象,它抛出异常(很明显)。

我不想再次进行数据库调用以再次从数据库中获取用户 ID。

我怎样才能实现它?

最佳答案

执行此操作的更好方法是创建一个 UserDetaisService,它返回一个扩展您的对象类型并实现 UserDetails 的对象。这意味着您只需执行一次数据库查找。

通过让 loadUserByUsername 的结果实现 UserDetails 并扩展您的 User 对象,您可以将其称为自定义用户对象,而 Spring Security 可以将其称为 UserDetails。

例如:

@Service
public class UserRepositoryUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;

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

    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username);
        if(user == null) {
            throw new UsernameNotFoundException("Could not find user " + username);
        }
        return new UserRepositoryUserDetails(user);
    }

    private final static class UserRepositoryUserDetails extends User implements UserDetails {

        private UserRepositoryUserDetails(User user) {
            super(user);
        }

        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return AuthorityUtils.createAuthorityList("ROLE_USER");
        }

        @Override
        public String getUsername() {
            return getEmail();
        }

        @Override
        public boolean isAccountNonExpired() {
            return true;
        }

        @Override
        public boolean isAccountNonLocked() {
            return true;
        }

        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }

        @Override
        public boolean isEnabled() {
            return true;
        }

        private static final long serialVersionUID = 5639683223516504866L;
    }
}

然后您可以在您的配置中引用自定义的 UserDetailsS​​ervice。例如:

<security:authentication-manager>
  <security:authentication-provider user-service-ref="customUserDetails" />
</security:authentication-manager>
<bean id="customUserDetails" class="sample.UserRepositoryUserDetailsService"/>

如果您使用的是 Spring Security 3.2.x+,则可以使用 Spring Security 的 @AuthenticationPrincipal解析自定义用户对象。例如:

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {

    // .. find messags for this user and return them ...
}

否则您可以使用以下内容:

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(Authentication auth) {
        User customUser = (User) auth.getPrincipal();
     ...
}

如果使用 XML 配置,则需要向 Spring MVC 注册 AuthenticationPrincipalArgumentResolver。

<mvc:annotation-driven>
  <mvc:argument-resolvers>
    <beans:bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver"/>
  </mvc:argument-resolvers>
</mvc:annotation-driven>

您可以在我的 github sample project 中找到有关此的详细信息.自述文件还引用了 the recorded webinar .

关于java - spring security 从数据库中获取用户 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29327159/

相关文章:

java - 当不可编辑时,将插入符保持在TextArea中

java - 有没有办法避免 Jackson 序列化未获取的惰性属性

java - 从 JSP 检索嵌套列表的值并将其发送回表单

spring - 如何在 Spring Boot 中禁用 http 服务器?

java - 使用 CommonsMultipartResolver 测试最大上传大小时“未找到多部分边界”

java - Spring Boot 无法解析 View

java - OpenJDK 在 Ubuntu 上看不到文件

java - 使用一个来源的两个 GUI

java - 为什么 Spring 有 taglibs 和velocity/freemarker 宏?这不是反春吗?

Spring root 和 servlet 上下文以及 Java 配置