Spring 安全登录总是登陆一个没有消息的错误页面 [英] Spring security login always lands in an error page with no message
问题描述
我在 Spring 的一个小项目中使用登录表单,但我有一个小问题,即每次我使用登录表单登录时,都会收到错误重定向.
这是我的 SecurityConfiguration.java
package com.ffuentese;导入 javax.sql.DataSource;导入 org.springframework.beans.factory.annotation.Autowired;导入 org.springframework.beans.factory.annotation.Value;导入 org.springframework.context.annotation.Configuration;导入 org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;导入 org.springframework.security.config.annotation.web.builders.HttpSecurity;导入 org.springframework.security.config.annotation.web.builders.WebSecurity;导入 org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;导入 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;导入 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;导入 org.springframework.security.web.util.matcher.AntPathRequestMatcher;@配置@启用网络安全公共类 SecurityConfiguration 扩展了 WebSecurityConfigurerAdapter {@自动连线私人 BCryptPasswordEncoder bCryptPasswordEncoder;@自动连线私有数据源数据源;@Value("${spring.queries.users-query}")私人字符串用户查询;@Value("${spring.queries.roles-query}")私有字符串角色查询;@覆盖受保护的无效配置(AuthenticationManagerBuilder auth)抛出异常{授权.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery).dataSource(数据源).passwordEncoder(bCryptPasswordEncoder);}@覆盖protected void configure(HttpSecurity http) 抛出异常 {http.授权请求().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("密码").and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and().exceptionHandling().accessDeniedPage("/访问被拒绝");}@覆盖公共无效配置(WebSecurity web)抛出异常{网络.忽略().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");}}
我的登录表单:
<button class="btn btn-lg btn-primary btn-block" name="Submit" value="Login" type="Submit" th:text="Login"></button></表单>
我的 loginController.java
package com.ffuentese;导入 javax.validation.Valid;导入 org.springframework.beans.factory.annotation.Autowired;导入 org.springframework.security.core.Authentication;导入 org.springframework.security.core.context.SecurityContextHolder;导入 org.springframework.stereotype.Controller;导入 org.springframework.validation.BindingResult;导入 org.springframework.web.bind.annotation.RequestMapping;导入 org.springframework.web.bind.annotation.RequestMethod;导入 org.springframework.web.servlet.ModelAndView;导入 com.ffuentese.User;@控制器公共类登录控制器{@自动连线私人用户服务用户服务;@RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)公共 ModelAndView 登录(){ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("登录");返回模型和视图;}@RequestMapping(value="/home", method = RequestMethod.GET)公共 ModelAndView homeV(){ModelAndView modelAndView = new ModelAndView();身份验证 auth = SecurityContextHolder.getContext().getAuthentication();modelAndView.setViewName("home");返回模型和视图;}@RequestMapping(value="/registration", method = RequestMethod.GET)公共 ModelAndView 注册(){ModelAndView modelAndView = new ModelAndView();用户用户 = 新用户();modelAndView.addObject("用户", 用户);modelAndView.setViewName("注册");返回模型和视图;}@RequestMapping(value = "/registration", method = RequestMethod.POST)public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {ModelAndView modelAndView = new ModelAndView();用户 userExists = userService.findUserByEmail(user.getEmail());如果(用户存在!= null){绑定结果.rejectValue("email", "error.user",已经有用户使用提供的电子邮件注册了");}如果(bindingResult.hasErrors()){modelAndView.setViewName("注册");} 别的 {userService.saveUser(user);modelAndView.addObject("successMessage", "用户注册成功");modelAndView.addObject("user", new User());modelAndView.setViewName("注册");}返回模型和视图;}@RequestMapping(value="/admin/home", method = RequestMethod.GET)公共 ModelAndView 主页(){ModelAndView modelAndView = new ModelAndView();身份验证 auth = SecurityContextHolder.getContext().getAuthentication();用户用户 = userService.findUserByEmail(auth.getName());modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");modelAndView.addObject("adminMessage","内容仅适用于具有管理员角色的用户");modelAndView.setViewName("admin/home");返回模型和视图;}}
所以,不是从登录到/home,它最终会登陆/error.错误本身是这样一行代码:
<块引用>{"timestamp":"2018-04-04T21:28:28.944+0000","status":999,"error":"None","message":"No消息可用"}
该表单确实有效,因为如果我从/error 移动并转到任何受保护的 URL,它们都可以打开.
原始代码来自此存储库,我将其改编为我自己的项目 https://github.com/gustavoponce7/SpringSecurityLoginTutorial 还解释了 这里
我认为重要的另一点是,如果我登录然后再次登录,表单似乎可以正常工作,让用户按预期从登录到/home.很奇怪.
也许就是这样,没有 RequestMapping
与 Param
错误.可能的解决方案
@RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)public ModelAndView login(@RequestParam(value = "error", required = false)){ModelAndView modelAndView = new ModelAndView();如果(错误!= null){modelAndView.setViewName("错误页面");} else modelAndView.setViewName("登录");返回模型和视图;}
编辑 1
也可能是因为您的项目中没有以下所有文件夹"/static/**", "/js/**", "/css/**", "/img/**", "/json/**"
, 删除此配置或添加所有文件夹.
I'm using a login form for a small project in Spring but I have a small problem which is that every time I log in using a sign in form I get an error redirection.
This is my 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/**");
}
}
My sign in form:
<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>
My loginController.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;
}
}
So, instead of going from login to /home it ends up landing in /error. The error itself is a line of code like this:
{"timestamp":"2018-04-04T21:28:28.944+0000","status":999,"error":"None","message":"No message available"}
The form does work because if I move from /error and go to any protected URL they can be opened.
EDIT: The original code comes from this repository and I adapted it to my own project https://github.com/gustavoponce7/SpringSecurityLoginTutorial also explained here
EDit: Another point I think it's important is that if I login and then login again the form seems to work alright taking the user from login to /home as expected. It's odd.
Maybe this is about that, there is no RequestMapping
with Param
error. Possible solution
@RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false)){
ModelAndView modelAndView = new ModelAndView();
if (error != null) {
modelAndView.setViewName("error page");
} else modelAndView.setViewName("login");
return modelAndView;
}
Edit1
Might be also caused by not having all following folders in your project "/static/**", "/js/**", "/css/**", "/img/**", "/json/**"
, delete this configure or add all folders.
这篇关于Spring 安全登录总是登陆一个没有消息的错误页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!