java - Spring Security 登录总是登陆一个没有消息的错误页面

标签 java spring spring-security

我在 Spring 中为一个小项目使用登录表单,但我有一个小问题,即每次我使用登录表单登录时,我都会收到错误重定向。

这是我的 SecurityConfiguration.java

package com.ffuentese;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private DataSource dataSource;

    @Value("${spring.queries.users-query}")
    private String usersQuery;

    @Value("${spring.queries.roles-query}")
    private String rolesQuery;

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.
            jdbcAuthentication()
                .usersByUsernameQuery(usersQuery)
                .authoritiesByUsernameQuery(rolesQuery)
                .dataSource(dataSource)
                .passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.
            authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/registration").permitAll()
                .antMatchers("/**").hasAuthority("ADMIN").anyRequest()
                .authenticated().and().csrf().disable().formLogin()
                .loginPage("/login").failureUrl("/login?error=true")
                .defaultSuccessUrl("/home")
                .usernameParameter("email")
                .passwordParameter("password")
                .and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/").and().exceptionHandling()
                .accessDeniedPage("/access-denied");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
           .ignoring()
           .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
    }

}

我的登录表单:

<form th:action="@{/login}" method="POST" class="form-signin">
    <h3 class="form-signin-heading" th:text="Welcome"></h3>
    <br/>

    <input type="text" id="email" name="email"  th:placeholder="Email"
        class="form-control" /> <br/> 
    <input type="password"  th:placeholder="Password"
        id="password" name="password" class="form-control" /> <br /> 

    <div align="center" th:if="${param.error}">
        <p style="font-size: 20; color: #FF1C19;">Email or contraseña errónea, por favor intente nuevamente.</p>
    </div>
    <button class="btn btn-lg btn-primary btn-block" name="Submit" value="Login" type="Submit" th:text="Login"></button>
</form>

我的登录 Controller .java

package com.ffuentese;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.ffuentese.User;

@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)
    public ModelAndView login(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("login");
        return modelAndView;
    }

    @RequestMapping(value="/home", method = RequestMethod.GET)
    public ModelAndView homeV(){
        ModelAndView modelAndView = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        modelAndView.setViewName("home");
        return modelAndView;
    }


    @RequestMapping(value="/registration", method = RequestMethod.GET)
    public ModelAndView registration(){
        ModelAndView modelAndView = new ModelAndView();
        User user = new User();
        modelAndView.addObject("user", user);
        modelAndView.setViewName("registration");
        return modelAndView;
    }

    @RequestMapping(value = "/registration", method = RequestMethod.POST)
    public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {
        ModelAndView modelAndView = new ModelAndView();
        User userExists = userService.findUserByEmail(user.getEmail());
        if (userExists != null) {
            bindingResult
                    .rejectValue("email", "error.user",
                            "There is already a user registered with the email provided");
        }
        if (bindingResult.hasErrors()) {
            modelAndView.setViewName("registration");
        } else {
            userService.saveUser(user);
            modelAndView.addObject("successMessage", "User has been registered successfully");
            modelAndView.addObject("user", new User());
            modelAndView.setViewName("registration");

        }
        return modelAndView;
    }

    @RequestMapping(value="/admin/home", method = RequestMethod.GET)
    public ModelAndView home(){
        ModelAndView modelAndView = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.findUserByEmail(auth.getName());
        modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");
        modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
        modelAndView.setViewName("admin/home");
        return modelAndView;
    }


}

因此,不是从登录到/home,而是最终进入/error。错误本身是这样一行代码:

{"timestamp":"2018-04-04T21:28:28.944+0000","status":999,"error":"None","message":"No message available"}

该表单确实有效,因为如果我从/error 移动到任何 protected URL,它们都可以打开。

编辑:原始代码来自这个存储库,我将其改编为我自己的项目https://github.com/gustavoponce7/SpringSecurityLoginTutorial还解释了here

编辑:我认为重要的另一点是,如果我登录然后再次登录,表单似乎可以正常工作,让用户按预期从登录到/home。这很奇怪。

最佳答案

您可以将 always-use-default-target 参数添加到成功 URL。

.defaultSuccessUrl("/home",true)

这意味着如果登录成功,您将始终被发送到/home

我认为不良行为是由错误页面由于某种原因而排队引起的,然后当登录成功时,您会“返回”到该页面。

这不是理想的解决方案,但如果您不想在登录后转到上一页,那么它可以防止您描述的行为。

关于java - Spring Security 登录总是登陆一个没有消息的错误页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49660763/

相关文章:

java - 用 java 函数转置 double[][] 矩阵?

java - 如何在html中设置@modelattribute boolean 值

java - neo4j 中不区分大小写的过滤器

java - Spring Boot Actuator Endpoints 安全性不适用于自定义 Spring 安全配置

java - 如何在 Spring 应用程序中检索 InMemoryUserDetailsManager 实例?

spring-security - 如何在 Spring Security 应用程序中列出*所有*用户和*所有*权限

java - "Extends JFrame"和 JPanel?

java - Java中如何计算一个对象的实例数?

eclipse - 警告 : No mapping found for HTTP request with URI [/PMC/] in DispatcherServlet with name 'spring-dispatcher'

java - 从 Hibernate persistenceContext 缓存中排除 JPA 实体?