Spring Security UserNotFoundException 在带有 JSP 视图模板的 Spring Boot 中不显示错误消息
Posted
技术标签:
【中文标题】Spring Security UserNotFoundException 在带有 JSP 视图模板的 Spring Boot 中不显示错误消息【英文标题】:Spring security UserNotFoundException not show error message in Spring Boot with JSP view template 【发布时间】:2020-09-28 06:36:21 【问题描述】:我正在使用 Spring Boot 和 JSP 创建一个 Web 应用程序。我已经实现了 Spring Security 并且我正在覆盖 loadUserByUsername()
方法,当找不到用户时,我会抛出 UsernameNotFoundException("User not found")
一条消息。现在我想在我的登录页面中显示一条正确的消息,我该如何实现?
MyUserDetailsService.java
package in.bushansirgur.security.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import in.bushansirgur.security.entity.Role;
import in.bushansirgur.security.entity.User;
@Service
public class MyUserDetailsService implements UserDetailsService
@Autowired
private UserService userService;
@Override
@Transactional
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException
User user = userService.findUserByEmail(email);
if(user == null || user.getActive() == null)
throw new UsernameNotFoundException("User not found!");
List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
return buildUserForAuthentication(user, authorities);
...
LoginController.java
@RequestMapping(value = "/login", "/")
public ModelAndView login(@RequestParam(name="error", required = false)String error,
@RequestParam(name="logout", required = false)String logout, HttpServletRequest request
) throws UnknownHostException
// Port
String portNumber = environment.getProperty("server.port");
// Local address
String hostAddress = InetAddress.getLocalHost().getHostAddress();
String hostName = InetAddress.getLocalHost().getHostName();
System.out.println("Host address:"+hostAddress+" Host name:"+hostName+" Port number:"+portNumber);
// Remote address
InetAddress.getLoopbackAddress().getHostAddress();
InetAddress.getLoopbackAddress().getHostName();
ModelAndView mv = new ModelAndView("login");
if(error!=null)
mv.addObject("message", "Invalid Username and Password!");
if(logout!=null)
mv.addObject("logout", "User has successfully logged out!");
System.out.println("context path:"+request.getContextPath());
return mv;
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<c:set var="contextRoot" value="$pageContext.request.contextPath" />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<style>
.help-block
color: #ff0000;
</style>
<body>
<h1>Login</h1>
<c:if test="$not empty message">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<div class="alert alert-danger">$message</div>
</div>
</div>
</c:if>
<c:if test="$not empty logout">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<div class="alert alert-success">$logout</div>
</div>
</div>
</c:if>
<form action="login" method="post" id="loginform">
<input type="text" name="email" placeholder="Enter email" /><br/>
<input type="password" name="password" placeholder="Enter password" /><br/>
<button type="submit">Login</button>
<%-- <input type="hidden" name="$_csrf.parameterName" value="$_csrf.token" /> --%>
</form>
<a href="$contextRoot/registration">Register</a>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.17.0/dist/jquery.validate.js"></script>
<script>
$(function()
const $loginForm = $("#loginform");
if($loginForm.length)
$loginForm.validate(
rules:
email:
required: true
,
password:
required: true
,
messages:
email:
required: "Please enter email"
,
password:
required: "Please enter password"
,
errorElement: 'em',
errorPlacement: function(error, element)
error.addClass('help-block');
error.insertAfter(element);
)
)
</script>
</body>
</html>
WebSecurityConfiguration.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/confirm-account").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAnyAuthority("ADMIN", "USER")
.anyRequest().authenticated().and().csrf().disable().formLogin()
.loginPage("/login")//.failureUrl("/login?error=true")
.defaultSuccessUrl("/dashboard")
.usernameParameter("email")
.passwordParameter("password")
.and().exceptionHandling().accessDeniedPage("/403");
...
JSP 中显示的错误消息是“无效的用户名和密码”。那么如果抛出UserNotFoundException
,如何显示“找不到用户”之类的错误消息!
提前致谢!
【问题讨论】:
不要显示该消息,因为这是一个安全风险。只显示一般消息。 那么,我现在显示的用户名和密码无效,可以吗? 【参考方案1】:默认情况下,如果找不到用户名或密码不正确,AbstractUserDetailsAuthenticationProvider
会抛出 BadCredentialsException。
将此属性设置为 false 将导致 UsernameNotFoundExceptions
被抛出而不是前者。
请注意,对于这两个异常,这被认为不如抛出 BadCredentialsException
安全。为此,您必须实例化您的身份验证提供程序,如下所示:
@Bean
public AuthenticationProvider daoAuthenticationProvider()
DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
impl.setUserDetailsService(yourUserDetailsService());
impl.setHideUserNotFoundExceptions(false) ;
return impl ;
警告:这样做不是很好的安全做法。
见here、setHideUserNotFoundExceptions和spring security bad credentials distinguish between invalid username or password
【讨论】:
以上是关于Spring Security UserNotFoundException 在带有 JSP 视图模板的 Spring Boot 中不显示错误消息的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security:2.4 Getting Spring Security
没有 JSP 的 Spring Security /j_spring_security_check
Spring Security 登录错误:HTTP 状态 404 - /j_spring_security_check