问题描述
在使用springsecurity进行登陆认证时,出现如下错误
class org.springframework.security.core.userdetails.User cannot be cast to class com.lp.common.mode.LoginUser
意思是说
类org.springframework.security.core.userdetails.User不能强制转换为类com.lp.common.mode.LogUser
以下是我的代码:
从写的loadUserByUsername方法
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 获取用户信息
// System.out.println(username);
TUser tUser = tUserService.getUserInfoByName(username);
// System.out.println(tUser);
if (StringUtils.isNull(tUser)){
throw new UserException("user is not null",null);
}
List<GrantedAuthority> arrayList = new ArrayList<>();
List<TRoles> roles = tUser.getRoles();//获取用户角色权限
if (roles != null && roles.size() > 0){//遍历角色
for (TRoles role : roles) {
arrayList.add(new SimpleGrantedAuthority(role.getRole_key()));
}
}
// passWordService.validate(tUser);//密码验证
// return createLoginUser(tUser);
return new User(username,tUser.getPassword(),arrayList);
LoginUser类
package com.lp.common.model;
import com.lp.common.entity.domain.TRoles;
import com.lp.common.entity.domain.TUser;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
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.Set;
/**
* @author LuoPing
* @date 2022/10/8 10:51
* 登陆实体
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements Serializable, UserDetails {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 用户唯一标识
*/
private String token;
/**
* 登录时间
*/
private Date loginTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 用户信息
*/
private TUser tUser;
private Set<String> roles;
public LoginUser(Long id, TUser tUser, Set<String> role) {
this.tUser = tUser;
this.userId = id;
this.roles = role;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Date getLoginTime() {
return loginTime;
}
public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
}
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public String getLoginLocation() {
return loginLocation;
}
public void setLoginLocation(String loginLocation) {
this.loginLocation = loginLocation;
}
public String getBrowser() {
return browser;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public TUser gettUser() {
return tUser;
}
public void settUser(TUser tUser) {
this.tUser = tUser;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return tUser.getPassword();
}
@Override
public String getUsername() {
return tUser.getPassword();
}
/**
* 账户是否未过期,过期无法验证
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 指定用户是否解锁,锁定的用户无法进行身份验证
*
* @return
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
*
* @return
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 是否可用 ,禁用的用户不能身份验证
*
* @return
*/
@Override
public boolean isEnabled() {
return true;
}
}
原因分析:
网上资料显示,问题在于UserDetailsServiceImpl.loadUserByUsername(…)的返回语句。不能将User转换为LoginUser对象,因为它们完全不同。应该返回扩展UserDetails创建的对象。
解决方案:
因为LoginUser实现了Userdetais接口,因此我们在loadUserByUsername中返回即可:
修改后代码如下:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 获取用户信息
// System.out.println(username);
TUser tUser = tUserService.getUserInfoByName(username);
// System.out.println(tUser);
if (StringUtils.isNull(tUser)){
throw new UserException("user is not null",null);
}
List<GrantedAuthority> arrayList = new ArrayList<>();
List<TRoles> roles = tUser.getRoles();//获取用户角色权限
if (roles != null && roles.size() > 0){//遍历角色
for (TRoles role : roles) {
arrayList.add(new SimpleGrantedAuthority(role.getRole_key()));
}
}
// passWordService.validate(tUser);//密码验证
return createLoginUser(tUser);
// return new User(username,tUser.getPassword(),arrayList);
}
private UserDetails createLoginUser(TUser tUser) {
String token = IdUtils.fastUUID();//生成token
//这里使用建造者模式创建,因为LoginUser中添加的@Builder注解
return LoginUser.builder()
.userId(tUser.getId())
.token(token)
.tUser(tUser)
.roles(permissionService.getRole(tUser))
.build();
}