有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个简单的弹簧靴2。xx应用程序使用Spring Data JPA MySQL,我必须使用Spring Security(特别是Java config)来保护这个web应用程序。在这方面,我在网上找到了大量资源来完成这项工作,但徒劳了,有些示例太复杂了,无法理解,而其他示例对我来说从未奏效。我想出了这个secure-spring-demo,它也不起作用。一些代码剪报是

WebSecurity配置类是

@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();
    }
}

而UserDetailsServiceImpl类是

@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
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");
    }

}

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


共 (2) 个答案

  1. # 1 楼答案

    我在你的代码中发现的主要问题是没有从thymeleaf模板中传递“username”和“password”属性,因为它应该与准确的凭据属性相匹配,以便对对象进行身份验证。。因此,您的登录表单如下所示:

     <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>
    1. 由于参数已更改,因此您还需要更改控制器属性:

      @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");
      }
      
  2. # 2 楼答案

    主要原因,因为您希望自定义方法处理spring security的登录,但您再次设置了自定义方法的名称,该名称与spring security的方法登录默认值相同。所以Web会调用spring的登录方法,但不会调用自定义方法

    在这种情况下,如果要自定义spring security的方法登录,必须将其转换为与spring login default的方法名不同的名称。这是你的建议,我可以听从

    我在登录文件中将“login”编辑为loginCustom。html

    login.xml

    在用户控制器中。java,我编辑为“/loginCustom” enter image description here