使用 Spring Security + Spring 数据 + MongoDB 进行身份验证

Posted

技术标签:

【中文标题】使用 Spring Security + Spring 数据 + MongoDB 进行身份验证【英文标题】:Authentication with Spring Security + Spring data + MongoDB 【发布时间】:2015-06-18 19:41:27 【问题描述】:

我想将 Spring 安全性与 MongoDB 一起使用(使用 Spring 数据)并从我自己的数据库中检索用户以实现 Spring 安全性。但是,我不能这样做,因为我的用户服务类型似乎不受支持。

这是我的 UserService 类:

public class UserService 
    private ApplicationContext applicationContext;
    private MongoOperations mongoOperations;

    public UserService() 
        applicationContext = new AnnotationConfigApplicationContext(MongoConfig.class);
        mongoOperations = (MongoOperations) applicationContext.getBean("mongoTemplate");
    

    public User find(String username) 
        return mongoOperations.findOne(Query.query(Criteria.where("username").is(username)), User.class);
    

还有我的 SecurityConfig 类:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    UserService userService;

    @Autowired
    public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception 
        builder.userDetailsService(userService); //THIS DOES NOT WORK
        builder.inMemoryAuthentication().withUser("username").password("password").roles("USER");
    


我评论的那行说:

The inferred type UserService is not a valid substitute for the bounded parameter <T extends UserDetailsService>.

我该如何解决它,以便我可以从我自己的数据库中检索用户?

【问题讨论】:

【参考方案1】:

创建您自己的身份验证提供程序,提供一个扩展 UserDetailservice 的类。 确保在您的 spring 上下文 xml 文件中启用内容扫描。

    <authentication-provider user-service-ref="userModelService">
        <password-encoder hash="sha" />
    </authentication-provider>

@Service
public class UserModelService implements UserDetailsService

@Autowired
private UserModelRepositoryImpl repository;



public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException

    UserModel user = repository.findByUsername(username);

     if( user == null )
        throw new UsernameNotFoundException( "Name not found!" );

      List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));

      return new User(user.getUsername(), user.getSHA1Password(), authorities );
 

public void saveUserDetails(UserModel userModel)

    repository.save(userModel);

这个类将为认证所需的用户名和密码启用spring查询mongo。接下来创建用户模型类。

public class UserModel


private String id;
@Indexed(unique=true)
private String username;
private String password;
 public String getUsername() 
    return username;

public void setUsername(String username) 
    this.username = username;

public String getPassword() 
    return password;

public void setPassword(String password) 
    this.password = password;

创建扩展 DAO 的用户实现类。

@Service
public class UserModelService implements UserDetailsService

@Autowired
private UserModelRepositoryImpl repository;



public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException

    UserModel user = repository.findByUsername(username);

     if( user == null )
        throw new UsernameNotFoundException( "Oops!" );

      List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));

      return new User(user.getUsername(), user.getSHA1Password(), authorities );
 

最后配置好 mongo 就大功告成了。

【讨论】:

【参考方案2】:

服务层

您必须创建一个单独的 service 实现 org.springframework.security.core.userdetails.UserDetailsService 并将其注入到 AuthenticationManagerBuilder 中。

@Component
public class SecUserDetailsService implements UserDetailsService

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        /*Here add user data layer fetching from the MongoDB.
          I have used userRepository*/
        User user = userRepository.findByUsername(username);
        if(user == null)
            throw new UsernameNotFoundException(username);
        else
            UserDetails details = new SecUserDetails(user);
            return details;
        
    

型号

UserDetails 也应该实现。这是 POJO,它将通过 Spring 保留用户经过身份验证的详细信息。您可以像我所做的那样将您的 Entity 数据对象包含在其中。

public class SecUserDetails implements UserDetails 

    private User user;

    public SecUserDetails(User user) 
        this.user = user;
    
    ......
    ......
    ......

安全配置

自动装配我们之前创建的服务并将其设置在AuthenticationManagerBuilder

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    SecUserDetailsService userDetailsService ;

    @Autowired
    public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception 
        builder.userDetailsService(userDetailsService); 
    

【讨论】:

安全专家就在身边! :) 永远感谢法拉杰! 您能否在答案中也包含“imports”?我对用户类感到困惑。这是一个自定义模型类吗?

以上是关于使用 Spring Security + Spring 数据 + MongoDB 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 不显示错误消息

Spring Security:简单的保护一个SpringBoot应用程序(总结)

Understand Spring Security Architecture and implement Spring Boot Security

为啥 https 中使用 Spring Security 添加端口 80?

带有 grails 的 Spring Security 核心插件

springboot中使用spring security,登录url就出现403错误