使用Spring Security和MongoDB完成用户认证

2017 Feb 28

一个简单的利用Spring Security实现用户登陆(用户认证)的例子。 使用MongoDB作为数据库来存储用户名和密码。

Spring Security的用户认证默认没有集成MongoDB。 可以通过实现AuthenticationProvider接口来完成个性化的用户认证。

@Component
public class AuthenticationProviderImpl implements AuthenticationProvider{
    @Autowired
    private UserRepository repository;
    
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        List<User> users = repository.findByAccount(username);
        if (users.isEmpty()) {
            throw new UsernameNotFoundException("user not found");
        }
        User user = users.get(0);
        if (!passwordEncoder.matches(password, user.getEncodedPassword())) {
            throw new BadCredentialsException("user name or password is invalid");
        }
        
        // NOTE: should provide @authorities param, otherwise the returned authentication's authorities will not
        // match the configuration in WebSecurityConfigurerAdapter. And it causes "defaultSuccessUrl" unaccessible
        // due to authorities mismatch.
        // 注意第三个参数,需要和WebSecurityConfigurerAdapter配置的role一致
        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
                authentication.getName(), authentication.getCredentials(), Roles.USER_AUTHORITIES);
        return result;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        // 表示这个AuthenticationProvider支持简单的用户名密码登陆
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

UserRepository是利用Spring Data MongoDB来实现的一个DAO。

public interface UserRepository extends MongoRepository<User, ObjectId>{
    List<User> findByAccount(String account);
}

密码使用BCryptPasswordEncoder来加密,更安全

Spring Security的配置如下。