在使用Spring Security的自定义认证之前,有必要了解Spring Security是如何灵活集成多种认证方式的。在spring Security中用户被称为主体(principal),主体包含了所有能够验证而获得系统访问权限的用户、设备或其他系统。主体的概念来自Java Security,自定义认证的基类是Authentication
public interface Authentication extends Principal, Serializable {
// ~ Methods
// ========================================================================================================
/**
* Set by an <code>AuthenticationManager</code> to indicate the authorities that the
* principal has been granted. Note that classes should not rely on this value as
* being valid unless it has been set by a trusted <code>AuthenticationManager</code>.
* <p>
* Implementations should ensure that modifications to the returned collection array
* do not affect the state of the Authentication object, or use an unmodifiable
* instance.
* </p>
*
* @return the authorities granted to the principal, or an empty collection if the
* token has not been authenticated. Never null.
*/
// 权限列表
Collection<? extends GrantedAuthority> getAuthorities();
/**
* The credentials that prove the principal is correct. This is usually a password,
* but could be anything relevant to the <code>AuthenticationManager</code>. Callers
* are expected to populate the credentials.
*
* @return the credentials that prove the identity of the <code>Principal</code>
*/
// 密码
Object getCredentials();
/**
* Stores additional details about the authentication request. These might be an IP
* address, certificate serial number etc.
*
* @return additional details about the authentication request, or <code>null</code>
* if not used
*/
// 其他信息
Object getDetails();
/**
* The identity of the principal being authenticated. In the case of an authentication
* request with username and password, this would be the username. Callers are
* expected to populate the principal for an authentication request.
* <p>
* The <tt>AuthenticationManager</tt> implementation will often return an
* <tt>Authentication</tt> containing richer information as the principal for use by
* the application. Many of the authentication providers will create a
* {@code UserDetails} object as the principal.
*
* @return the <code>Principal</code> being authenticated or the authenticated
* principal after authentication.
*/
// 用户名
Object getPrincipal();
/**
* Used to indicate to {@code AbstractSecurityInterceptor} whether it should present
* the authentication token to the <code>AuthenticationManager</code>. Typically an
* <code>AuthenticationManager</code> (or, more often, one of its
* <code>AuthenticationProvider</code>s) will return an immutable authentication token
* after successful authentication, in which case that token can safely return
* <code>true</code> to this method. Returning <code>true</code> will improve
* performance, as calling the <code>AuthenticationManager</code> for every request
* will no longer be necessary.
* <p>
* For security reasons, implementations of this interface should be very careful
* about returning <code>true</code> from this method unless they are either
* immutable, or have some way of ensuring the properties have not been changed since
* original creation.
*
* @return true if the token has been authenticated and the
* <code>AbstractSecurityInterceptor</code> does not need to present the token to the
* <code>AuthenticationManager</code> again for re-authentication.
*/
// 是否验证成功
boolean isAuthenticated();
/**
* See {@link #isAuthenticated()} for a full description.
* <p>
* Implementations should <b>always</b> allow this method to be called with a
* <code>false</code> parameter, as this is used by various classes to specify the
* authentication token should not be trusted. If an implementation wishes to reject
* an invocation with a <code>true</code> parameter (which would indicate the
* authentication token is trusted - a potential security risk) the implementation
* should throw an {@link IllegalArgumentException}.
*
* @param isAuthenticated <code>true</code> if the token should be trusted (which may
* result in an exception) or <code>false</code> if the token should not be trusted
*
* @throws IllegalArgumentException if an attempt to make the authentication token
* trusted (by passing <code>true</code> as the argument) is rejected due to the
* implementation being immutable or implementing its own alternative approach to
* {@link #isAuthenticated()}
*/
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
一、分析UsernamePasswordAuthenticationFilter#attemptAuthentication源码
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
// 获取用户名和密码
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
Userna