2011-04-12 80 views
1

如果我想检查凭证是否有效,如何继续?Spring Security如何检查登录表单凭证是否有效?

例如,我想确保用户名是有效的(有效的电子邮件,有限的大小等等),以便我甚至可以在尝试使用Spring Security进行身份验证之前向用户显示错误。

1)确保证书认证 2)验证 3)摇滚正卷

顺便说一句,我使用Spring Security的3.1.0 RC之前是有效的。

预先感谢您的帮助, 阿德南

更新: 其实我说的是验证:确保用户名是有效的电子邮件格式,或请确保密码至少为8个字符,依此类推。 只有当我确定它处于“有效”格式时,我才会将其提交给安全身份验证&授权,否则我只想再次显示带有错误消息的登录表单(例如:“密码必须至少包含8个字符“)。

回答

1

您可能想要跳过登录验证,并且仅在注册/编辑配置文件/更改密码时进行验证。当他们尝试使用错误的用户名/密码进行登录时,它将不会被发现。

我可以看到两种方法来做你想做的。通常,登录页面会使用j_username和j_password POST到/ j_spring_security_check。 UsernamePasswordAuthenticationFilter拦截此POST并委托给AuthenticationManager及其AuthenticationProviders(通常是DaoAuthenticationProvider)。

如果你真的想在它碰到任何Spring Security代码之前进行验证,你需要在UsernamePasswordAuthenticationFilter之前添加一个Filter并在那里进行验证。

或者,子类DaoAuthenticationProvider和覆盖retreiveUser()。在retrieveUser()中进行额外的验证,如果验证失败则抛出异常。

配置您的子类作为像这样的身份验证提供者:

<authentication-manager> 
    <authentication-provider ref='myAuthenticationProvider'/> 
</authentication-manager> 
+0

其实我在谈论验证,确保用户名是有效的电子邮件格式,或确保密码至少8个字符等等。 当然,我需要在服务器端进行验证,而不必考虑它也可以在客户端完成。 (问题已更新) – 2011-04-12 14:22:47

+0

更新了我的回复。我看到你的答案,这绝对是可行的 - 但它绕过了标准的Spring Security流程。 – sourcedelica 2011-04-12 16:53:17

-1

好吧,我找到了一种方法使用Hibernate的验证器注解@Email & NOTNULL等验证表单字段:

import javax.validation.constraints.Size; 

import org.hibernate.validator.constraints.Email; 
import org.hibernate.validator.constraints.NotBlank; 

public class LoginForm 
{ 
    @Email 
    @Size(min = 4, max = 128) 
    private String username; 

    @NotBlank 
    @Size(min = 4, max = 128) 
    private String password; 

    ... 

} 

安全部分有点棘手,因为我必须手动对authenticationManager进行身份验证,并且安全上下文不想更新当前会话:

@Autowired 
@Qualifier("authenticationManager") 
private AuthenticationManager authenticationManager; 

@RequestMapping(method = RequestMethod.POST) 
public String processForm(@Valid LoginForm loginForm, BindingResult result, HttpServletRequest request, Model model) 
{ 
    // Display errors in loginForm if not valid 
    if (result.hasErrors()) 
     return "login"; 

    try 
    { 
     UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginForm.getUsername(), loginForm.getPassword()); 
     Authentication auth = authenticationManager.authenticate(token); 
     SecurityContextHolder.getContext().setAuthentication(auth); 

     // for some reason, security context is NOT setting the auth key in session 
     // so I had to put it here myself! 
     HttpSession session = request.getSession(); 
     session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); 

     return "redirect:/index"; 
    } 
    catch (AuthenticationException e) 
    { 
     SecurityContextHolder.getContext().setAuthentication(null); 
     String errorMessage = e.getLocalizedMessage(); 
     model.addAttribute("errorMessage", errorMessage); 
     return "loginerror"; 
    } 
} 

请务必将别名认证管理器,以便能够自动装配它<security:authentication-manager alias="authenticationManager">

希望帮助别人:)

+0

我认为这不是验证表单数据的正确方法。验证应该发生在过滤器链本身中。例如,您可以重写UsernamePasswordAuthenticationFilter的attemptAuthentication方法或requireAuthentication方法,并调用hibernate验证器来验证LoginForm。 – Ritesh 2011-04-12 17:56:49

0

如果环境支持的Servlet 3.0+,您可以在使用HttpServletRequest.login(username, password)你的控制器方法。