#java #spring-boot #kotlin
Вопрос:
Я пытаюсь передать элемент InstaUserDetails в функции карты с помощью ссылки на метод . Я хочу передать весь пользовательский элемент, полученный из базы данных, потому что класс InstaUserDetails расширяет класс пользователя. Но когда я передаю пользовательские данные внутри функции карты, они показывают следующий тип ошибки
Type mismatch.
Required:
((User!) → TypeVariable(U)!)!
Found:
KFunction9<String, String, String, String, LocalDate, LocalDate, Boolean, Profile, (Mutable)Set<Role!>, InstaUserDetails
InstaUserDetails.java
package com.nilmani.mychat.model;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.time.LocalDate;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
public class InstaUserDetails extends User implements UserDetails {
public InstaUserDetails(@NotNull String id, @NotNull String userName, @NotNull String password, @NotNull String email, @NotNull LocalDate createdAt, @NotNull LocalDate updatedAt, boolean active, @NotNull Profile userProfile, @NotNull Set<Role> role) {
super(id, userName, password, email, createdAt, updatedAt, active, userProfile, role);
}
/**
* Returns the authorities granted to the user. Cannot return <code>null</code>.
*
* @return the authorities, sorted by natural key (never <code>null</code>)
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRole()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" role.getName()))
.collect(Collectors.toList());
}
/**
* Returns the username used to authenticate the user. Cannot return
* <code>null</code>.
*
* @return the username (never <code>null</code>)
*/
@Override
public String getUsername() {
return "userName";
}
/**
* Indicates whether the user's account has expired. An expired account cannot be
* authenticated.
*
* @return <code>true</code> if the user's account is valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
@Override
public boolean isAccountNonExpired() {
return isAccountNonExpired();
}
/**
* Indicates whether the user is locked or unlocked. A locked user cannot be
* authenticated.
*
* @return <code>true</code> if the user is not locked, <code>false</code> otherwise
*/
@Override
public boolean isAccountNonLocked() {
return isAccountNonLocked();
}
/**
* Indicates whether the user's credentials (password) has expired. Expired
* credentials prevent authentication.
*
* @return <code>true</code> if the user's credentials are valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
@Override
public boolean isCredentialsNonExpired() {
return isCredentialsNonExpired();
}
/**
* Indicates whether the user is enabled or disabled. A disabled user cannot be
* authenticated.
*
* @return <code>true</code> if the user is enabled, <code>false</code> otherwise
*/
@Override
public boolean isEnabled() {
return isEnabled();
}
}
Пользователь.kt
package com.nilmani.mychat.model
import org.jetbrains.annotations.NotNull
import org.springframework.data.mongodb.core.mapping.Document
import java.time.Instant
import java.time.LocalDate
@Document
open class User(
var id:String="",
var userName:String="",
var password:String="",
var email:String="",
var createdAt:LocalDate=LocalDate.now(),
var updatedAt:LocalDate= LocalDate.now(),
var active:Boolean=false,
@NotNull
var userProfile:Profile,
@NotNull
var role:Set<Role> = HashSet()
)
JwtTokenAuthenticationFilter.kt
package com.nilmani.mychat.config
import com.nilmani.mychat.model.InstaUserDetails
import com.nilmani.mychat.model.Profile
import com.nilmani.mychat.model.Role
import com.nilmani.mychat.service.JwtTokenProvider
import com.nilmani.mychat.service.UserService
import io.jsonwebtoken.Claims
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
import org.springframework.web.filter.OncePerRequestFilter
import java.io.IOException
import java.time.LocalDate
import java.util.*
import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
class JwtTokenAuthenticationFilter(jwtConfig: JwtConfig, jetTokenProvider: JwtTokenProvider, userService: UserService) : OncePerRequestFilter() {
@Autowired
private lateinit var jwtConfig: JwtConfig
@Autowired
private lateinit var jwtTokenProvider: JwtTokenProvider
@Autowired
private lateinit var userService: UserService
/**
* Same contract as for `doFilter`, but guaranteed to be
* just invoked once per request within a single request thread.
* See [.shouldNotFilterAsyncDispatch] for details.
*
* Provides HttpServletRequest and HttpServletResponse arguments instead of the
* default ServletRequest and ServletResponse ones.
*/
@Throws(IOException::class,ServletException::class)
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
val header:String = request.getHeader(jwtConfig.header)
if (header == null || !header.startsWith(jwtConfig.prefix)){
filterChain.doFilter(request,response)
return
}
val token:String = header.replace(jwtConfig.prefix,"")
if (jwtTokenProvider.validateToken(token)){
val claims:Claims = jwtTokenProvider.getClaimsFromJWT(token)
val username:String = claims.subject
val auth:UsernamePasswordAuthenticationToken =
userService.findByUserName(username)
.map(::InstaUserDetails)
.map { userDetails ->
val authentication = UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.authorities
)
authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
authentication
}
.orElse(null)
SecurityContextHolder.getContext().authentication=auth
}else{
SecurityContextHolder.clearContext()
}
filterChain.doFilter(request,response)
}
}
Как передать пользовательские данные без каких-либо ошибок внутри
Фильтр проверки подлинности JW.kt
Ошибка отображается в этой конкретной точке
val auth:UsernamePasswordAuthenticationToken =
userService.findByUserName(username)
.map(::InstaUserDetails)
.map { userDetails ->
val authentication = UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.authorities
До того, как мой класс фильтров будет выглядеть следующим образом
val username:String = claims.subject
val auth:UsernamePasswordAuthenticationToken =
userService.findByUserName(username)
.map { id: String, userName: String, password: String, email: String, createdAt: LocalDate, updatedAt: LocalDate, active: Boolean, userProfile: Profile, role: Set<Role> ->
InstaUserDetails(
id!!,
userName!!,
password!!,
email!!,
createdAt!!,
updatedAt!!,
active,
userProfile!!,
role!!
)
Комментарии:
1. Каков тип возвращаемых данных
findByUserName()
? Вообще говоря, конструктор вашегоInstaUserDetails
получает несколько аргументов, но вы пытаетесь вызвать его только с одним аргументом, который является каким-то пользовательским объектом. Вам необходимо создать дополнительный конструктор, который принимает этот однопользовательский объект, или развернуть данные вmap()
нем .2. Если я разверну данные на карте() Это показывает ту же ошибку , я уже пробовал этот способ, но я хочу вернуть данные InstaUserDetails, как я могу это сделать
3. Что ты пробовал? Это должно быть что-то вроде:
map { InstaUserDetails(...) }
и вам нужно указать все 9 параметров, как вы бы создавалиInstaUserDetails
объект в любом другом месте, за пределамиmap()
.4. Я расширяю данные в map() следующим образом .map { идентификатор: Строка, Имя пользователя: Строка, пароль: Строка, электронная почта: Строка, Созданное: Локальная дата, обновленное: Локальная дата, активное: Логическое значение, Профиль пользователя: Профиль, роль: Установить<Роль> )
5. Какой тип объектов возвращается
findByUserName()
? Это тот жеUser
самый объект, которыйInstaUserDetails
расширяется?