简体   繁体   English

spring mvc + spring security,登录后出现404

[英]Spring mvc + spring security, a 404 after log in

I'm new to spring security and I'm into a small trouble with it.我是 Spring Security 的新手,遇到了一些小麻烦。

So I have 2 model classes :所以我有 2 个模型类:

User :用户:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    @NotEmpty
    private String email;
    @NotEmpty
    private String password;
    @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
    private Set<UserRole> roles = new HashSet<>();

UserRole:用户角色:

    @Id
    @GeneratedValue
    private Long id;
    private String role;
    private String description;

At the moment of registration user is assigned a ROLE_USER by default.在注册时,默认情况下为用户分配了ROLE_USER

I made own UserDetailsService implementation :我做了自己的UserDetailsService实现:

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username);
        if (user == null)
            throw new UsernameNotFoundException("User not found");
        return new org.springframework.security.core.userdetails.User(
                user.getEmail(),
                user.getPassword(),
                convertAuthorities(user.getRoles())
        );
    }

    private Set<GrantedAuthority> convertAuthorities(Set<UserRole> userRoles) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        for (UserRole ur : userRoles) {
            authorities.add(new SimpleGrantedAuthority(ur.getRole()));
        }
        return authorities;
    }

And my security config :我的安全配置:

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").permitAll().usernameParameter("email").passwordParameter("password")
                .and().logout().logoutSuccessUrl("/").invalidateHttpSession(true).and().csrf();
    }

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

Registration is succesfull in the /register controller./register控制器中注册成功。

After when I want to login with the same credentials the problem occurs.当我想使用相同的凭据登录后,就会出现问题。 From the login form I'm sending a POST request to /login controller.我从登录表单向/login控制器发送 POST 请求。

Form :形式 :

<form class="form-signin" action="#" th:action="@{/login}" method="post">
        <h2 class="form-signin-heading">Please log in</h2>
        <label for="inputEmail" class="sr-only">Email address</label>
        <input type="email" name="email" id="inputEmail" class="form-control" placeholder="Email address" th:required="required"></input>
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" th:required="required"></input>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>

/login controller : /login控制器:

@PostMapping("/login")
    public String processLogin(){
        logger.debug("processLogin");
        return "secure";
}

The /login controller should return the secure page but instead I'm receiving an 404 error /login控制器应该返回secure页面,但我收到了 404 错误

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Mon Mar 13 21:17:02 CET 2017
There was an unexpected error (type=Not Found, status=404).
No message available

Like I said, I'm new in spring security and I don't what is wrong ...就像我说的,我是春季安全新手,我不知道有什么问题......

您必须在 spring security 中提供authentication-failure-url在安全配置中添加此代码formLogin().loginPage("/login").failureUrl("/loginPage?error")

I am using an easy way to handle HTTP errors in my Spring MVC + Spring Security app:我正在使用一种简单的方法来处理 Spring MVC + Spring Security 应用程序中的 HTTP 错误:

I declared all errors I want to handle in web.xml我在 web.xml 中声明了我想处理的所有错误

<error-page>
    <!-- Missing login -->
    <error-code>400</error-code>
    <location>/in_general-error</location>
</error-page>
    <error-page>
    <!-- Missing login -->
    <error-code>401</error-code>
    <location>/in_general-error</location>
</error-page>
<error-page>
    <!-- Forbidden directory listing -->
    <error-code>403</error-code>
    <location>/in_general-error</location>
</error-page>
<error-page>
    <!-- Missing resource -->
    <error-code>404</error-code>
    <location>/in_general-error</location>
</error-page>
<error-page>
    <!-- Uncaught exception -->
    <error-code>500</error-code>
    <location>/in_general-error</location>
</error-page>
<error-page>
    <!-- Unsupported servlet method -->
    <error-code>503</error-code>
    <location>/in_general-error</location>
</error-page>

As you can see in location there is not a page but an URI.正如您在 location 中看到的,不是页面而是 URI。 Of course you have to allow access to that URI in your Spring Security configuration.当然,您必须在 Spring Security 配置中允许访问该 URI。 And you have to handle that URI in your Controller:您必须在控制器中处理该 URI:

@RequestMapping(value = "/in_general-error", method = RequestMethod.GET)
    public ModelAndView generalError() {        
        return new ModelAndView("general-error");
    }

And thats all.就这样。 There are other solutions but this is the easiest you can find.还有其他解决方案,但这是您能找到的最简单的解决方案。

@Bartosz - you need to create your 'secure.html' file in the src/main/resources/templates directory in your project. @Bartosz - 您需要在项目的 src/main/resources/templates 目录中创建“secure.html”文件。 Then when your LoginController.java returns "secure" it will find the thymeleaf template file there.然后当您的 LoginController.java 返回“secure”时,它会在那里找到 thymeleaf 模板文件。

LoginController.java登录控制器.java

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LoginController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    String login(HttpServletRequest request, Model model) {
        return "secure";
    }
}

secure.html安全.html

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body onload="document.f.username.focus();">
<div class="container">
    <div class="navbar">
        <div class="navbar-inner">
            <a class="brand" href="https://www.thymeleaf.org"> Thymeleaf - Plain </a>
            <ul class="nav">
                <li><a th:href="@{/}" href="home.html"> Home </a></li>
            </ul>
        </div>
    </div>
    <div class="content">
        <p th:if="${param.logout}" class="alert">You have been logged out</p>
        <p th:if="${param.error}" class="alert alert-error">There was an error,  please try again</p>
        <h2>Login with Username and Password</h2>
        <form name="form" th:action="@{/login}" action="/login" method="POST">
            <fieldset>
                <input type="text" name="username" value="" placeholder="Username" />
                <input type="password" name="password" placeholder="Password" />
            </fieldset>
            <input type="submit" id="login" value="login" 
                class="btn btn-primary" />
        </form>
    </div>
</div>

</body>
</html>

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

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