在Spring登录中显示错误消息

Jul*_*ius 5 security authentication spring login messages

我正在使用Spring安全性对用户进行身份验证。我创建了一个自定义身份验证提供程序,现在我想知道如何将错误消息从提供程序获取到表单中。这是我的自定义身份验证提供程序中的authenticate()方法:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    UserProfile profile = userProfileService.findByEmail(authentication.getPrincipal().toString());

    if(profile == null){
        throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));
    }

    String suppliedPasswordHash = DigestUtils.shaHex(authentication.getCredentials().toString());

    if(!profile.getPasswordHash().equals(suppliedPasswordHash)){
        throw new BadCredentialsException("Invalid credentials");
    }

    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(profile, null, profile.getAuthorities());

    return token;
}
Run Code Online (Sandbox Code Playgroud)

这是我的表格:

<form name='f' action="<c:url value='j_spring_security_check' />" method='POST'>
<div id="data-entry-form">

    <div class="form-entry">
        <label><spring:message code="login.form.label.email"/></label>
        <input type='text' name='j_username' value=''>
    </div>
    <div class="form-entry">
        <label><spring:message code="login.form.label.password"/></label>
        <input type='password' name='j_password'/>
    </div>
    <div class="form-entry">
        <input type="submit" value="Verzenden"/>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

如何将错误消息发送到表单中?从我按下登录按钮的那一刻起,Spring接管了工作,因此我可以生成错误消息的唯一方法是authenticate()方法。

Yan*_*Pak 14

最安全方法的 3 个步骤(我们不依赖 LAST_EXCEPTION):

  1. 在自定义身份验证提供程序的配置中指定错误页面(例如“登录错误”)

    httpSecurity
    .authorizeRequests()
    .antMatchers("/css/**", "/js/**", "/img/**").permitAll()
    .anyRequest().fullyAuthenticated()
    .and()
    .formLogin().loginPage("/login").permitAll()
    .failureUrl("/login-error")
    .and()
    .logout().permitAll()
    
    Run Code Online (Sandbox Code Playgroud)
  2. 为 url /login-error 创建控制器,使用下一个代码返回自定义登录页面的视图(例如“登录”):

    @Controller
    public class LoginController {
    
        @GetMapping("/login-error")
        public String login(HttpServletRequest request, Model model) {
            HttpSession session = request.getSession(false);
            String errorMessage = null;
            if (session != null) {
                AuthenticationException ex = (AuthenticationException) session
                        .getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
                if (ex != null) {
                    errorMessage = ex.getMessage();
                }
            }
            model.addAttribute("errorMessage", errorMessage);
            return "login";
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 最后将错误消息放入您的页面(例如 ThymeLeaf 标签):

    <!--/*@thymesVar id="errorMessage" type="java.lang.String"*/-->
    <div class="alert" th:if="${errorMessage}" th:text="${errorMessage}"></div>
    
    Run Code Online (Sandbox Code Playgroud)


vad*_*ipp 5

我能够像这样解决它:

<c:if test="${param.auth eq 'failure'}">
  <div class="error">
    <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
  </div>
</c:if>
Run Code Online (Sandbox Code Playgroud)

请注意,您需要通过一个特殊参数来检测是否存在错误,您可以在 spring-security 配置中设置该参数,如下所示:

<security:form-login [...] authentication-failure-url="/login?auth=failure" />
Run Code Online (Sandbox Code Playgroud)

编辑: 实际上,没有必要传递该参数。相反,可以简单地检查是否SPRING_SECURITY_LAST_EXCEPTION.message已定义,如下所示:

<c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION.message}">
  <div class="error">
    <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
  </div>
</c:if>
Run Code Online (Sandbox Code Playgroud)


dru*_*lik 4

我认为您应该能够以与使用“标准”身份验证器相同的方式获取消息。如果在身份验证过程中引发异常(或多个异常),则最后一个异常将存储在会话属性中:SPRING_SECURITY_LAST_EXCEPTION。

因此,要从 JSP 获取最后一条异常消息,您可以使用如下内容:

<%=((Exception) request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION")).getMessage()%>;
Run Code Online (Sandbox Code Playgroud)

当然,如果您有控制器,您可能应该从控制器获取消息并仅将字符串传递给 jsp。这只是一个例子;)