1.说明
此示例,是在(spring security入门--从数据库读取数据实现用户登录访问简单示例四)的基础上改用了自定义UserDetails实现用户登录访问,因为这里只修改了实体类User和UserService中的代码,其他代码请参见示例四
地址:https://blog.csdn.net/qq_32224047/article/details/108607746
2.代码示例
因为要实现UserDetails自定义,在User类中实现接口UserDetails,然后重写里面的方法
注意:
1.实现接口方法后,返回值都需要修改为true
2.重写的getAuthorities()方法返回的值不能为null,否则返回的永远是null,就会一直没有权限,由此定义了一个authorities 属性并提供get方法,因为自 定义了UserDetails,就没有在UserService中,使用到框架提供的User对象
3.需要重写equals方法,默认使用恒等去判断是否是同一个对象,因为登录的同一个用户,如果再次登录就会封装
一个新的对象,这样会导致登录的用户永远不会相等,所以需要重写equals方法
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
public class User implements Serializable, UserDetails {
private Long id;
private String username;
private String password;
private String phone;
private Date created;
private Date updated;
private List<GrantedAuthority> authorities;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String getUsername() {
return username;
}
//继承后必须返回为true
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setUsername(String username) {
this.username = username;
}
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
//返回的值不能为null,否则返回的永远是null,就会一直没有权限,由此定义了一个authorities 属性并提供get方法,因为自
// 定义了UserDetails,就没有在UserService中,使用到框架提供的User对象
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
//不能返回null
return authorities;
}
@Override
public String getPassword() {
return password;
}
//默认使用恒等去判断是否是同一个对象,因为登录的同一个用户,如果再次登录就会封装
//一个新的对象,这样会导致登录的用户永远不会相等,所以需要重写equals方法
@Override
public boolean equals(Object obj) {
//会话并发生效,使用username判断是否是同一个用户
if (obj instanceof User){
//字符串的equals方法是已经重写过的
return ((User) obj).getUsername().equals(this.username);
}else {
return false;
}
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
}
这里不再使用security提供的User类,将获取的authorities设置到自定义的user实体中,在重写的getAuthorities方法中return
import cn.wy.domain.Permission;
import cn.wy.mapper.PermissionMapper;
import cn.wy.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
/**
* 用于读取Mapper数据库数据,要和Security整合,需要
* 实现接口UserDetailsService
*
*/
public class UserService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Autowired
private PermissionMapper permissionMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//username参数,是在登陆时,用户传递的表单数据username
//主要读取数据库3个值 username password authorities
//这里自定义的User和security中的User重名,且那个包名很长所以这里写自定义User的包路径
cn.wy.domain.User user = userMapper.selectUserByUsername(username);
Long userId=user.getId();
List<Permission> permissions = permissionMapper.selectPermissionsByUserid(userId);
//为了返回一个UserDetails 使用User
List<GrantedAuthority> authorities=new ArrayList<>();
for (Permission p:permissions) {
//循环一次,就拿到了表格权限,使用authority字段
String authorityName = p.getAuthority();
GrantedAuthority authority=
new SimpleGrantedAuthority(authorityName);
authorities.add(authority);
}
//将获取的authorities设置到自定义的user实体中,在重写的getAuthorities方法中return
user.setAuthorities(authorities);
return user;
}
//注入permissionMapper userMapper读数据库数据
}
3.运行测试
user用户
admin用户