java - 在 Spring Security 中使用 UserDetails 实现登录不起作用

标签 java spring-boot spring-security

我有一个带有 Spring Data JPA MySQL 的简单 Spring Boot 2.xx 应用程序,我必须使用 Spring Security(尤其是 Java 配置)来保护这个 Web 应用程序,在这方面,我在网上找到了大量资源来完成工作,但是 <强>徒劳,有些例子太复杂而难以理解,而其他例子从来没有在我这边起作用。我想出了这个secure-spring-demo ,这也不起作用。一些代码片段是

WebSecurityConfig 类是

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }


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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http
                .authorizeRequests()
                .antMatchers("/login*", "/register", "/").anonymous()
                .antMatchers("/secure/*").hasAnyAuthority("ADMIN").anyRequest().authenticated()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .and()
                .logout().logoutSuccessUrl("/login");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

而 UserDetailsS​​erviceImpl 类是

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserService userService;

    @Autowired
    public UserDetailsServiceImpl(UserService userService) {
        this.userService = userService;
    }

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userService.findByUserEmail(s);
        if (user == null){
            throw new UsernameNotFoundException("User with " + s + " not found!");
        }

        return new org.springframework.security.core.userdetails.User(
                user.getUserEmail(), user.getUserPassword(), user.getRoles());
    }
}

Controller 是

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private SecurityService securityService;

    //Omitting other mappings

    @GetMapping(value = "/login")
    public String getLogin(Model model,
                           @RequestParam(value = "error", required = false) String error){
        if (null != error && error.equalsIgnoreCase("true")){
            model.addAttribute("loginError", "Unable to Login");
        }
        return "login";
    }

    @PostMapping(value = "/login")
    public String postLogin(@RequestParam(value = "userEmail") String userEmail,
                              @RequestParam(value = "userPassword") String userPassword){
        logger.debug(userEmail + " and " + userPassword );
        boolean loginResult = securityService.login(userEmail, userPassword);
        return (loginResult ? "redirect:/secure/home" : "redirect:/login?error=true");
    }

}

这样一来,所有用户都无法使用正确的凭据登录。

最佳答案

我在您的代码中发现的主要问题是没有从 thymeleaf 模板传递“用户名”和“密码”属性,因为它应该与精确的凭据属性匹配才能验证对象。因此您的登录表单将如下所示:

 <form th:method="post" th:action="@{/login}" enctype="utf8">
  <input th:type="email" name="username" placeholder="Email" required="">
  <input th:type="password" name="password" placeholder="Password" required="">
  <button th:type="submit" name="submit"> Login </button>
  <span>You Have No Account? <a th:href="@{/register}"> Create An Account</a></span>
 </form>

  • 由于参数已更改,因此您还需要更改 Controller 属性:

    @PostMapping(value = "/login")
    public String postLogin(@RequestParam(value = "username") String userEmail,
                              @RequestParam(value = "password") String userPassword){
        logger.debug(userEmail + " and " + userPassword );
        boolean loginResult = securityService.login(userEmail, userPassword);
        return (loginResult ? "redirect:/secure/home" : "redirect:/login?error=true");
    }
    
  • 关于java - 在 Spring Security 中使用 UserDetails 实现登录不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53029633/

    相关文章:

    Java AES-128 ECB 加密

    javax.mail.MessagingException : Could not connect to SMTP host: localhost, 端口:25

    java - Spring为什么单次调用@Cacheable注解方法会执行2次@Cacheable keyGenerator

    java - 如何为 Spring Boot 创建内部属性文件?

    java - Spring安全组件扫描

    spring-security - CSRF token 已关联到此客户端”而不禁用 CSRF

    java - 如何将模拟注入(inject)到需要构造函数参数的 bean 中

    Java Spring MVC 如何获取这个设定值?

    grails - 如何在Grails Spring Security中设置自定义超时以记住我的cookie?

    java - Spring 如何向 session 变量添加新的 _csrf token ?