問題描述
在使用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();
}