使用 UserDetailsS​​ervice 的 Spring Security 身份验证

Posted

技术标签:

【中文标题】使用 UserDetailsS​​ervice 的 Spring Security 身份验证【英文标题】:Spring Security authentication using UserDetailsService 【发布时间】:2015-06-02 20:13:29 【问题描述】:

我在使用 Spring 安全认证时遇到了一些问题。 在我的应用程序中,一切都运行良好(CRUD 操作运行良好),但登录尝试失败。

这是我的代码(我在下面用 cmets 标记,其中 userDAO 为 null,这是身份验证失败的原因):

@Service
public class UserServiceImpl implements UserService, UserDetailsService 

    @Autowired
    UserDAO userDAO;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        User user = userDAO.getUserByUsername(username); //userDAO == null Causing NPE
        if (user == null)
            throw new UsernameNotFoundException("Oops!");

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

        return new org.springframework.security.core.userdetails
                .User(user.getLogin(), user.getPassword(), authorities);
    

@Override
    public List<User> getUsers() 
        return userDAO.getUsers();//userDAO !=null
    
//rest of code skipped

我的 SecurityConfig 看起来像这样

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

 UserServiceImpl userService = new UserServiceImpl();

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(userService);
    
//rest of code skipped

我标记了我在哪里获得 NPE,但我不知道如何解决这个问题。整个配置是基于 Java 的,您可以在这里查看更多详细信息 HERE

编辑:getUsers() 在控制器中以这种方式调用:

@Controller
public class LoginController 
    @Autowired
    UserService userService;

 @RequestMapping(value = "/dashboard")
    public ModelAndView userDashboard()
        ModelAndView modelAndView = new ModelAndView("Dashboard");
        List<User> userList = userService.getUsers();
        modelAndView.addObject("users", userList);
        return modelAndView;
    

并且在这种情况下(调用 userService.getUsers() 时)userDAO 不为空

尝试像 Bohuslav Burghardt 建议的那样修复它,我得到了

 method userDetailsService in class org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder cannot be applied to given types;
  required: T
  found: com.gi.service.UserService
  reason: inferred type does not conform to upper bound(s)
    inferred: com.gi.service.UserService
    upper bound(s): org.springframework.security.core.userdetails.UserDetailsService

排队 auth.userDetailsS​​ervice(userService);

【问题讨论】:

【参考方案1】:

这是不正确的部分:

UserServiceImpl userService = new UserServiceImpl();

当您自己实例化服务时,其自动装配的依赖项将始终为null。您必须让 Spring 容器实例化它(已经通过使用 @Service 标记服务来完成),然后将其注入到您的安全配置类中,如下所示:

public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    private UserDetailsService userService;

【讨论】:

当我试图用你的方式修复它时,它显示 Error:(24, 13) java: method userDetailsS​​ervice in class org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder cannot be applied to给定类型;必需:T 找到:com.gi.service.UserService 原因:推断类型不符合上限推断:com.gi.service.UserService 上限:org.springframework.security.core.userdetails。用户详情服务 @d__k 您可以通过以下三种方式之一修复它:1) 将服务自动装配为私有 UserDetailsS​​ervice userService,2) 使您的 UserService 接口扩展 UserDetailsS​​ervice 接口,然后让您的实现类仅实现 UserService 或3)在配置类中将UserService强制转换为UserDetailsS​​ervice 尝试了这两种方法并得到:`没有为依赖项找到类型为 [com.gi.service.UserService] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。`跨度> 你可以随时查看我在 github 上的代码以获得广阔的视野【参考方案2】:

Bohuslav 的这段代码解决了问题

public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    private UserService userService;

也不见了

@ComponentScan("com.gi")

之前

public class SecurityConfig extends WebSecurityConfigurerAdapter 

缺乏导致

Error:(24, 13) java: method userDetailsService in class org.springframework.security.config.annotation.authentication.builders.Authentic‌​ationManagerBuilder cannot be applied to given types; required: T found: com.gi.service.UserService reason: inferred type does not conform to upper bound(s) inferred: com.gi.service.UserService upper bound(s): org.springframework.security.core.userdetails.UserDetailsService

【讨论】:

以上是关于使用 UserDetailsS​​ervice 的 Spring Security 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 JdbcUserDetailsManager 与自己的 UserDetailsS​​ervice

带有自定义 UserDetailsS​​ervice 的 Spring Boot

使用 userDetailsS​​ervice 的 Spring Boot 安全性

spring-security-oauth2 2.0.7 刷新令牌 UserDetailsS​​ervice 配置 - UserDetailsS​​ervice 是必需的

使用我的自定义 UserDetailsS​​ervice 后,httpsession 生命周期事件不起作用

Spring security - 未调用自定义 userDetailsS​​ervice 实现