我在配置spring security3中,有一个非常困惑的问题。
在登录页面,基于 /j_spring_security_check 的登录后,继承UserDetailsService接口,并且实现函数loadByUserName(String username)。
我要问的是,我如何取得密码?传递进来的只是一个帐户,没有密码。
还是我对登录这块理解错误?望指教。
load到了User对象后,框架会帮你匹配密码是否正确
去重新他的CustomUserDetails
示例代码:
[code="java"]
public class User extends IdEntity implements CustomUserDetails {
/**
*
*/
private static final long serialVersionUID = 1L;
private String userAccount;
private String userPassword;// 为简化演示使用明文保存的密码
private String userName;
private String issys;
private String userDesc;
private String userDuty;
private Integer deptId;
private String subSystem;
private String isenabled;
private List<Role> roleList = Lists.newArrayList();// 有序的关联对象集合
// 实现了UserDetails之后的相关变量
private Long userId;
private String password;
private String username;
private Set<GrantedAuthority> authorities;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private Set<Menus> menus = Sets.newTreeSet();
public User() {
}
public User(Long userId, String userAccount, String userName, String userPassword,
String desc, String duty, Integer dept, boolean enable,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Set<GrantedAuthority> authorities, Set<Menus> menus) {
this.userDuty = duty;
this.userDesc = desc;
this.deptId = dept;
this.userName = userName;
this.username = userAccount;
this.password = userPassword;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = authorities;
this.menus = menus;
this.userId = userId;
}
// 字段非空且唯一, 用于提醒Entity使用者及生成DDL.
@Column(nullable = false, unique = true)
public String getUserAccount() {
return userAccount;
}
public void setUserAccount(String userAccount) {
this.userAccount = userAccount;
}
// 多对多定义
@ManyToMany
// 中间表定义,表名采用默认命名规则
@JoinTable(name = "SYS_USERS_ROLES", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
// Fecth策略定义
@Fetch(FetchMode.SUBSELECT)
// 集合按id排序.
@OrderBy("id")
// 集合中对象id的缓存.
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public List<Role> getRoleList() {
return roleList;
}
public void setRoleList(List<Role> roleList) {
this.roleList = roleList;
}
/**
* 用户拥有的角色名称字符串, 多个角色名称用','分隔.
*/
// 非持久化属性.
@Transient
public String getRoleNames() {
return Converts.convertElementPropertyToString(roleList, "roleDesc",
", ");
}
/**
* 用户拥有的角色id字符串, 多个角色id用','分隔.
*/
// 非持久化属性.
@Transient
@SuppressWarnings("unchecked")
public List<Long> getRoleIds() {
return Converts.convertElementPropertyToList(roleList, "id");
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getIssys() {
return issys;
}
public String getSubSystem() {
return subSystem;
}
public String getUserDesc() {
return userDesc;
}
public String getUserDuty() {
return userDuty;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setUserDesc(String userDesc) {
this.userDesc = userDesc;
}
public void setIssys(String issys) {
this.issys = issys;
}
public void setUserDuty(String userDuty) {
this.userDuty = userDuty;
}
public void setSubSystem(String subSystem) {
this.subSystem = subSystem;
}
@Transient
@Override
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
@Transient
@Override
public String getPassword() {
return password;
}
@Transient
@Override
public String getUsername() {
return username;
}
@Transient
@Override
public boolean isAccountNonExpired() {
return accountNonExpired;
}
@Transient
@Override
public boolean isAccountNonLocked() {
return accountNonLocked;
}
@Transient
@Override
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
@Transient
@Override
public boolean isEnabled() {
return true;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getIsenabled() {
return isenabled;
}
public void setIsenabled(String isenabled) {
this.isenabled = isenabled;
}
@Transient
public Set<Menus> getMenus() {
return menus;
}
@Transient
public Long getUserId() {
return userId;
}
}
[/code]
[code="java"]
/**
*实现了UserDetails,扩展几项信息,比如getSubSystem()方法等 sparta 11/4/13。
*/
public interface CustomUserDetails extends UserDetails {
public Long getUserId();
//用户名
public String getUserName();
//用户描述或简介
public String getUserDesc();
//所属的单位
public Integer getDeptId();
//用户职位
public String getUserDuty();
public Set<Menus> getMenus();
}
[code="java"]
public class UserDetailsServiceImpl implements UserDetailsService {
private AccountManager accountManager;
/**
* 获取用户Details信息的回调函数.
*/
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
User user = accountManager.findUserByLoginName(username);
if (user == null) {
throw new UsernameNotFoundException("用户" + username + " 不存在");
}
Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(user);
Set<Menus> menu = getAllMenus(user);
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
/*
* UserDetails userdetails = new
* org.springframework.security.core.userdetails.User(
* user.getUserAccount(), user.getUserPassword(), enabled,
* accountNonExpired, credentialsNonExpired, accountNonLocked,
* grantedAuths);
*/
User userdetails = new User(user.getId(), user.getUserAccount(), user.getUserName(),
user.getUserPassword(), user.getUserDesc(), user.getUserDuty(),
user.getDeptId(), enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, grantedAuths, menu);
return userdetails;
}
/**
* 获得用户所有角色的权限集合.
*/
private Set<GrantedAuthority> obtainGrantedAuthorities(User user) {
Set<GrantedAuthority> authSet = Sets.newHashSet();
for (Role role : user.getRoleList()) {
for (Authority authority : role.getAuthorityList()) {
authSet.add(new GrantedAuthorityImpl(authority
.getPrefixedName()));
}
}
return authSet;
}
private Set<Menus> getAllMenus(User user) {
Set<Menus> menus = Sets.newTreeSet();
for (Role role : user.getRoleList()) {
for (Menus menu : role.getMenusList()) {
menus.add(menu);
}
}
return menus;
}
@Autowired
public void setAccountManager(AccountManager accountManager) {
this.accountManager = accountManager;
}
}
[/code]
[/code]
Spring Security3中loadByUserName(String username)只是根据用户名获取User实体。具体认证的过程中再验证该账号是否能够认证通过。至于密码判断部分的源码为
org.springframework.security.authentication.dao.DaoAuthenticationProvider类的additionalAuthenticationChecks方法
如果想更深入了解这个安全框架,可参考本人的专栏
http://dead-knight.iteye.com/admin/categories/220917