繁体   English   中英

Spring BOOT 安全性:自定义登录页面从不进行身份验证

[英]Spring BOOT security : Custom login page is never authenticating

我正在开发一个带有 Spring Boot 的网络应用程序。 我使用过 spring 引导安全。

如果我使用 spring boot 默认登录页面,身份验证按预期工作

但它不适用于自定义登录页面

如果我在 websecurity.java 中配置 http 端点时使用自定义登录页面,我将被重定向到登录页面

下面分享示例代码和我的诊断。

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated()
                .and().formLogin().loginPage("/loginPage")
                .permitAll();

    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(getPasswordEncoder());
    }

    private PasswordEncoder getPasswordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return true;
            }
        };
    }
}

控制器 :

@Controller
@EnableAutoConfiguration
@ComponentScan("com.shopping.service")
public class ShoppingController {

    @Autowired
    private ShoppingService service;

    @RequestMapping("/")
    public String index() {
        return "";
    }

    @RequestMapping("/loginPage")
    public String welcome(Map<String, Object> model) {
        return "login";
    }

    @RequestMapping(value = "/register")
    public String register(Model model) {
        model.addAttribute("user", new User());
        return "register";
    }

    @RequestMapping(value = "/submitRegistration", method = RequestMethod.POST)
    public String submitRegistration(@ModelAttribute User user) {
        User saved = service.save(user);
        System.out.println(saved);
        return "login";
    }

    @RequestMapping("/home")
    public String home() {
        return "home";
    }
}

登录.html:

<form th:action="@{/loginPage}" method="post" th:object="${object}">
    <div class="form-group">
<label for="username">Email address:</label>
<input type="email" name="username" class="form-control" id="username">
   </div>
    <div class="form-group">
        <label for="password">Password:</label>
        <input type="password" name="password" class="form-control" id="password">
    </div>
    <div class="checkbox">
        <label><input type="checkbox"> Remember me</label>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="/register" class="btn btn-default">Register</a>
</form>

使用 crud Repo 从数据库进行用户身份验证的 UserDetailsS​​ervice

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepo;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        Optional<User> optionalUser = userRepo.findByEmail(userName);
        optionalUser.orElseThrow(() -> new UsernameNotFoundException("User Name not found"));
        UserDetailsImpl userDetails = optionalUser.map(user -> new UserDetailsImpl(user)).get();
        return userDetails;
    }

}

public class UserDetailsImpl extends User implements UserDetails {

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    public UserDetailsImpl(User user) {
        this.setEmail(user.getEmail());
        this.setAge(user.getAge());
        this.setName(user.getName());
        this.setId(user.getId());
        this.setPassword(user.getPassword());
    }

    @Override
    public String getPassword() {
        return super.getPassword();
    }

    @Override
    public String getUsername() {
        return super.getEmail();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

您需要指定用户名的 ID/名称和密码参数。

默认值为usernamepassword ,但您使用emailpassword

您可以更改安全配置中的默认值:

//...
and().formLogin()
    .loginPage("/loginPage")
    .usernameParameter("email").passwordParameter("password")
//...

请注意,您只需要更改与默认值不同的方法,我只想展示这两种方法。

编辑 1

第二个错误是表单操作,它必须是loginPage("/loginPage")方法指定的loginPage("/loginPage") ,所以在这种情况下: th:action="@{/loginPage}"

此外,您的密码标签的 for 属性是错误的(在这种情况下必须是password )。

我对此进行了测试,现在对我有用。

编辑 2

Spring 安全性并不像您想象的那样工作。 它拦截表单的操作 URL 并将您重定向到您在登录之前尝试访问的页面。如果您想更改它,您可以使用successForwardUrl()

在你的例子中:

//...
and().formLogin()
    .loginPage("/loginPage")
    .successForwardUrl("/home")
//...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM