You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin+Spring Security实现UserDetails时password冲突如何解决?

问题根源

你遇到的冲突本质是两个原因叠加导致的:

  1. Kotlin中声明var password: String?时,编译器会自动生成签名为getPassword()Ljava/lang/String;的public getter方法,和setPassword(Ljava/lang/String;)V的public setter方法
  2. 你让InstaUserDetails同时继承了User类和实现了UserDetails接口,UserDetails本身就要求实现getPassword()方法,你还手动在InstaUserDetails里重写了getPassword(),导致和父类User自动生成的getPassword()JVM签名完全重复,所以报Accidental override错误。
    另外你当前写的InstaUserDetails里的isAccountNonExpired/isEnabled等方法都是递归调用自身,运行会直接栈溢出,属于逻辑错误。

最优解决方案(推荐)

遵循单一职责原则,不要让认证用的UserDetails实现类继承数据库实体类User,改用组合的方式持有User实例,完全避免签名冲突,代码耦合度也更低。

修改后的InstaUserDetails.kt代码

package com.nilmani.mychat.model

import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import java.util.stream.Collectors

// 不再继承User类,构造函数传入User实体
class InstaUserDetails(private val user: User) : UserDetails {
    override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
        return user.role
            ?.stream()
            ?.map { role -> SimpleGrantedAuthority("ROLE_"+role.name) }
            ?.collect(Collectors.toList())!!
    }
    // 直接返回user实体的password,不会出现方法冲突
    override fun getPassword() : String? {
        return user.password
    }
    override fun getUsername(): String? {
        return user.userName
    }
    override fun isAccountNonExpired(): Boolean {
        // 你没有设计账号过期字段,直接返回true即可
        return true
    }
    override fun isAccountNonLocked(): Boolean {
        return true
    }
    override fun isCredentialsNonExpired(): Boolean {
       return true
    }
    override fun isEnabled(): Boolean {
        return user.active
    }
}

User类不需要做任何修改

保持var password: String? =""的public声明即可,UserService中可以正常访问user.password赋值加密后的密码,不会有访问权限问题。

如果你非要让InstaUserDetails继承User的替代方案

删除InstaUserDetails中手动重写的getPassword()、getUsername()方法即可,因为父类User已经自动生成了对应签名的getter方法,刚好满足UserDetails接口的要求,不需要你重复实现。同时修复递归调用的问题:

class InstaUserDetails :User(),UserDetails {
    override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
        return role
            ?.stream()
            ?.map { role -> SimpleGrantedAuthority("ROLE_"+role.name) }
            ?.collect(Collectors.toList())!!
    }
    // 删掉多余的getPassword、getUsername方法
    override fun isAccountNonExpired(): Boolean = true
    override fun isAccountNonLocked(): Boolean = true
    override fun isCredentialsNonExpired(): Boolean = true
    override fun isEnabled(): Boolean = active
}

内容的提问来源于stack exchange,提问作者Mama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:39:02