常规的登录方式是用户名,密码登录。现在项目 中有这样的 需求:要求一台移动设备(手机或者平板)在不输入用户名和密码的情况下,也可以登录成功,前提是这台设备已经唯一绑定了一个用户,并发送了设备的相关信息。
要想加入自己的认证方式,就必须要了解Spring security 是怎样实现用户认证的。
先来了解下框架中的几个类:
1.UserDetails 接口 :提供核心的用户信息
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
package org.springframework.security.core.userdetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.io.Serializable;
import java.util.Collection;
/**
* Provides core user information.
*
* <p>
* Implementations are not used directly by Spring Security for security purposes. They
* simply store user information which is later encapsulated into {@link Authentication}
* objects. This allows non-security related user information (such as email addresses,
* telephone numbers etc) to be stored in a convenient location.
* <p>
* Concrete implementations must take particular care to ensure the non-null contract
* detailed for each method is enforced. See
* {@link org.springframework.security.core.userdetails.User} for a reference
* implementation (which you might like to extend or use in your code).
*
* @see UserDetailsService
* @see UserCache
*
* @author Ben Alex
*/
public interface UserDetails extends Serializable {
// ~ Methods
// ========================================================================================================
/**
* Returns the authorities granted to the user. Cannot return <code>null</code>.
*
* @return the authorities, sorted by natural key (never <code>null</code>)
*/
Collection<? extends GrantedAuthority> getAuthorities();
/**
* Returns the password used to authenticate the user.
*
* @return the password
*/
String getPassword();
/**
* Returns the username used to authenticate the user. Cannot return <code>null</code>
* .
*
* @return the username (never <code>null</code>)
*/
String getUsername();
/**
* Indicates whether the user's account has expired. An expired account cannot be
* authenticated.
*
* @return <code>true</code> if the user's account is valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
boolean isAccountNonExpired();
/**
* Indicates whether the user is locked or unlocked. A locked user cannot be
* authenticated.
*
* @return <code>true</code> if the user is not locked, <code>false</code> otherwise
*/
boolean isAccountNonLocked();
/**
* Indicates whether the user's credentials (password) has expired. Expired
* credentials prevent authentication.
*
* @return <code>true</code> if the user's credentials are valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
boolean isCredentialsNonExpired();
/**
* Indicates whether the user is enabled or disabled. A disabled user cannot be
* authenticated.
*
* @return <code>true</code> if the user is enabled, <code>false</code> otherwise
*/
boolean isEnabled();
}
2. User: UserDetails最直接的一个实现,该实现只要找到对应的用户名就算认证成功
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
package org.springframework.security.core.userdetails;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.Assert;
/**
* Models core user information retrieved by a {@link UserDetailsService}.
* <p>
* Developers may use this class directly, subclass it, or write their own
* {@link UserDetails} implementation from scratch.
* <p>
* {@code equals} and {@code hashcode} implementations are based on the {@code username}
* property only, as the intention is that lookups of the same user principal object (in a
* user registry, for example) will match where the objects represent the same user, not
* just when all the properties (authorities, password for example) are the same.
* <p>
* Note that this implementation is not immutable. It implements the
* {@code CredentialsContainer} interface, in order to allow the password to be erased
* after authentication. This may cause side-effects if you are storing instances
* in-memory and reusing them. If so, make sure you return a copy from your
* {@code UserDetailsService} each time it is invoked.
*
* @author Ben Alex
* @author Luke Taylor
*/
public class User implements UserDetails, CredentialsContainer {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
// ~ Instance fields
// ================================================================================================
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountNonExpired;
private final boolean accountNonLocked;
private final boolean credentialsNonExpired;
private final boolean enabled;
// ~ Constructors
// ===================================================================================================
/**
* Calls the more complex constructor with all boolean arguments set to {@code true}.
*/
public User(String username, String password,
Collection<? extends GrantedAuthority> authorities) {
this(username, password, true, true, true, true, authorities);
}
/**
* Construct the <co