Kaynağa Gözat

# feat:使用spring security实现系统的认证;
- 认证
- 认证异常处理
- 鉴权异常处理

yang yi 5 saat önce
ebeveyn
işleme
09c9281553

+ 6 - 2
build.gradle.kts

@@ -29,14 +29,18 @@ dependencies {
     // Source: https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter
     implementation ("com.baomidou:mybatis-plus-spring-boot3-starter:3.5.15")
 //    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
-//    implementation("org.springframework.boot:spring-boot-starter-security")
+    implementation("org.springframework.boot:spring-boot-starter-security")
     implementation("org.springframework.boot:spring-boot-starter-validation")
     implementation("org.springframework.boot:spring-boot-starter-web")
     implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.16")
     // Source: https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-3-starter
     implementation("com.alibaba:druid-spring-boot-3-starter:1.2.28")
     developmentOnly("org.springframework.boot:spring-boot-devtools")
-    runtimeOnly("org.postgresql:postgresql")
+    implementation("org.postgresql:postgresql")
+    // JWT
+    implementation("io.jsonwebtoken:jjwt-api:0.12.6")
+    runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")
+    runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6")
     annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
     testImplementation("org.springframework.boot:spring-boot-starter-test")
     testImplementation("org.springframework.security:spring-security-test")

+ 65 - 0
src/main/java/space/anyi/serve/config/SecurityConfig.java

@@ -0,0 +1,65 @@
+package space.anyi.serve.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import space.anyi.serve.filter.JwtAuthenticationFilter;
+import space.anyi.serve.handler.security.JwtAccessDeniedHandler;
+import space.anyi.serve.handler.security.JwtAuthenticationEntryPoint;
+
+@EnableWebSecurity
+@Configuration
+public class SecurityConfig {
+
+    private final JwtAuthenticationFilter jwtAuthenticationFilter;
+    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
+    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
+
+    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter,
+                          JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint,
+                          JwtAccessDeniedHandler jwtAccessDeniedHandler) {
+        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
+        this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
+        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
+        return configuration.getAuthenticationManager();
+    }
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+        http
+                .csrf(AbstractHttpConfigurer::disable)
+                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+                .authorizeHttpRequests(authorize -> authorize
+                        .requestMatchers("/auth/login", "/auth/register").permitAll()
+                        .requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll()
+                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+                        .anyRequest().authenticated()
+                )
+                .exceptionHandling(ex -> ex
+                        .authenticationEntryPoint(jwtAuthenticationEntryPoint)
+                        .accessDeniedHandler(jwtAccessDeniedHandler)
+                )
+                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
+
+        return http.build();
+    }
+}

+ 72 - 0
src/main/java/space/anyi/serve/controller/AuthController.java

@@ -0,0 +1,72 @@
+package space.anyi.serve.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import space.anyi.serve.entity.auth.JwtUserDetails;
+import space.anyi.serve.entity.Response;
+import space.anyi.serve.entity.auth.AuthTokenVo;
+import space.anyi.serve.entity.auth.LoginDto;
+import space.anyi.serve.entity.auth.RegisterDto;
+import space.anyi.serve.entity.user.User;
+import space.anyi.serve.handler.security.JwtTokenProvider;
+import space.anyi.serve.service.UserService;
+
+@Tag(name = "AuthController",description = "用户认证相关接口")
+@RestController
+@RequestMapping("auth")
+public class AuthController {
+
+    private final UserService userService;
+    private final AuthenticationManager authenticationManager;
+    private final JwtTokenProvider jwtTokenProvider;
+    private final PasswordEncoder passwordEncoder;
+
+
+    public AuthController(UserService userService,
+                          AuthenticationManager authenticationManager,
+                          JwtTokenProvider jwtTokenProvider, PasswordEncoder passwordEncoder) {
+        this.userService = userService;
+        this.authenticationManager = authenticationManager;
+        this.jwtTokenProvider = jwtTokenProvider;
+        this.passwordEncoder = passwordEncoder;
+    }
+
+    @Operation(summary = "用户登录")
+    @PostMapping("login")
+    public Response<AuthTokenVo> login(@Valid @RequestBody LoginDto loginDto) {
+        var authentication = authenticationManager.authenticate(
+                new UsernamePasswordAuthenticationToken(loginDto.getAccount(), loginDto.getPassword())
+        );
+        JwtUserDetails userDetails = (JwtUserDetails) authentication.getPrincipal();
+        var user = userDetails.getUser();
+        String token = jwtTokenProvider.generateToken(user.getId(), user.getAccount(), user.getUsername(), user.getRole());
+        return Response.ok(new AuthTokenVo(token, user.getId(), user.getAccount(), user.getUsername(), user.getRole()));
+    }
+
+    @Operation(summary = "用户注册")
+    @PostMapping("register")
+    public Response<AuthTokenVo> register(@Valid @RequestBody RegisterDto registerDto) {
+        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
+                .eq(User::getAccount, registerDto.getAccount());
+        if (userService.count(wrapper) > 0) {
+            throw new IllegalArgumentException("账号已存在");
+        }
+        User user = new User();
+        user.setAccount(registerDto.getAccount());
+        user.setPassword(passwordEncoder.encode(registerDto.getPassword()));
+        user.setUsername(registerDto.getUsername());
+        userService.save(user);
+        String token = jwtTokenProvider.generateToken(user.getId(), user.getAccount(), user.getUsername(), user.getRole());
+        AuthTokenVo authTokenVo = new AuthTokenVo(token, user.getId(), user.getAccount(), user.getUsername(), user.getRole());
+        return Response.ok(authTokenVo);
+    }
+}

+ 70 - 0
src/main/java/space/anyi/serve/entity/auth/AuthTokenVo.java

@@ -0,0 +1,70 @@
+package space.anyi.serve.entity.auth;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(description = "登录响应")
+public class AuthTokenVo {
+
+    @Schema(description = "JWT token")
+    private String token;
+
+    @Schema(description = "用户ID")
+    private Long userId;
+
+    @Schema(description = "账号")
+    private String account;
+
+    @Schema(description = "用户名")
+    private String username;
+
+    @Schema(description = "角色")
+    private String role;
+
+    public AuthTokenVo(String token, Long userId, String account, String username, String role) {
+        this.token = token;
+        this.userId = userId;
+        this.account = account;
+        this.username = username;
+        this.role = role;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+}

+ 57 - 0
src/main/java/space/anyi/serve/entity/auth/JwtUserDetails.java

@@ -0,0 +1,57 @@
+package space.anyi.serve.entity.auth;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import space.anyi.serve.entity.user.User;
+
+import java.util.Collection;
+import java.util.List;
+
+public class JwtUserDetails implements UserDetails {
+
+    private final User user;
+
+    public JwtUserDetails(User user) {
+        this.user = user;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return List.of(new SimpleGrantedAuthority("ROLE_" + user.getRole()));
+    }
+
+    @Override
+    public String getPassword() {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername() {
+        return user.getAccount();
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return true;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return user.getEnable() == 1;
+    }
+}

+ 32 - 0
src/main/java/space/anyi/serve/entity/auth/LoginDto.java

@@ -0,0 +1,32 @@
+package space.anyi.serve.entity.auth;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+
+@Schema(description = "登录请求参数")
+public class LoginDto {
+
+    @NotBlank(message = "账号不能为空")
+    @Schema(description = "账号")
+    private String account;
+
+    @NotBlank(message = "密码不能为空")
+    @Schema(description = "密码")
+    private String password;
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}

+ 48 - 0
src/main/java/space/anyi/serve/entity/auth/RegisterDto.java

@@ -0,0 +1,48 @@
+package space.anyi.serve.entity.auth;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+@Schema(description = "注册请求参数")
+public class RegisterDto {
+
+    @NotBlank(message = "账号不能为空")
+    @Size(min = 4, max = 20, message = "账号长度不能小于4且不能大于20")
+    @Schema(description = "账号", minLength = 4, maxLength = 20)
+    private String account;
+
+    @NotBlank(message = "密码不能为空")
+    @Size(min = 4, max = 20, message = "密码长度不能小于4且不能大于20")
+    @Schema(description = "密码", minLength = 4, maxLength = 20)
+    private String password;
+
+    @NotBlank(message = "用户名不能为空")
+    @Size(min = 2, max = 32, message = "用户名长度不能小于2且不能大于32")
+    @Schema(description = "用户名", minLength = 2, maxLength = 32)
+    private String username;
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+}

+ 56 - 0
src/main/java/space/anyi/serve/filter/JwtAuthenticationFilter.java

@@ -0,0 +1,56 @@
+package space.anyi.serve.filter;
+
+import io.jsonwebtoken.Claims;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+import space.anyi.serve.handler.security.JwtTokenProvider;
+
+import java.io.IOException;
+import java.util.List;
+
+@Component
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+
+    private final JwtTokenProvider jwtTokenProvider;
+
+    public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
+        this.jwtTokenProvider = jwtTokenProvider;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request,
+                                    HttpServletResponse response,
+                                    FilterChain filterChain) throws ServletException, IOException {
+        String token = extractToken(request);
+
+        if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
+            Claims claims = jwtTokenProvider.parseToken(token);
+            String account = claims.getSubject();
+            String role = claims.get("role", String.class);
+
+            List<SimpleGrantedAuthority> authorities = List.of(new SimpleGrantedAuthority("ROLE_" + role));
+
+            UsernamePasswordAuthenticationToken authentication =
+                    new UsernamePasswordAuthenticationToken(account, null, authorities);
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+
+        filterChain.doFilter(request, response);
+    }
+
+    private String extractToken(HttpServletRequest request) {
+        String header = request.getHeader("Authorization");
+        if (StringUtils.hasText(header) && header.startsWith("Bearer ")) {
+            return header.substring(7);
+        }
+        return null;
+    }
+}

+ 33 - 0
src/main/java/space/anyi/serve/handler/security/JwtAccessDeniedHandler.java

@@ -0,0 +1,33 @@
+package space.anyi.serve.handler.security;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+import space.anyi.serve.entity.Response;
+
+import java.io.IOException;
+
+@Component
+public class JwtAccessDeniedHandler implements AccessDeniedHandler {
+
+    private final ObjectMapper objectMapper;
+
+    public JwtAccessDeniedHandler(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+    @Override
+    public void handle(HttpServletRequest request,
+                       HttpServletResponse response,
+                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
+        response.setStatus(HttpStatus.FORBIDDEN.value());
+        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+        response.getWriter().write(objectMapper.writeValueAsString(Response.error("无权限访问")));
+    }
+}

+ 33 - 0
src/main/java/space/anyi/serve/handler/security/JwtAuthenticationEntryPoint.java

@@ -0,0 +1,33 @@
+package space.anyi.serve.handler.security;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import space.anyi.serve.entity.Response;
+
+import java.io.IOException;
+
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+    private final ObjectMapper objectMapper;
+
+    public JwtAuthenticationEntryPoint(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+    @Override
+    public void commence(HttpServletRequest request,
+                         HttpServletResponse response,
+                         AuthenticationException authException) throws IOException, ServletException {
+        response.setStatus(HttpStatus.UNAUTHORIZED.value());
+        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+        response.getWriter().write(objectMapper.writeValueAsString(Response.error("未认证或认证已过期")));
+    }
+}

+ 74 - 0
src/main/java/space/anyi/serve/handler/security/JwtTokenProvider.java

@@ -0,0 +1,74 @@
+package space.anyi.serve.handler.security;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.io.Decoders;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.SecretKey;
+import java.util.Date;
+import java.util.Map;
+
+@Component
+public class JwtTokenProvider {
+
+    private static final String SECRET = "YW55aS1zZXJ2ZS1qd3Qtc2VjcmV0LWtleS1tdXN0LWJlLWF0LWxlYXN0LTI1Ni1iaXRz";
+    private static final long EXPIRATION_MS = 86400000L; // 24 hours
+
+    private SecretKey getSigningKey() {
+        byte[] keyBytes = Decoders.BASE64.decode(SECRET);
+        return Keys.hmacShaKeyFor(keyBytes);
+    }
+
+    public String generateToken(Long userId, String account,String username, String role) {
+        return Jwts.builder()
+                .claims(Map.of(
+                        "userId", userId,
+                        "account", account,
+                        "username", username,
+                        "role", role
+                ))
+                .subject(account)
+                .issuedAt(new Date())
+                .expiration(new Date(System.currentTimeMillis() + EXPIRATION_MS))
+                .signWith(getSigningKey())
+                .compact();
+    }
+
+    public Claims parseToken(String token) {
+        return Jwts.parser()
+                .verifyWith(getSigningKey())
+                .build()
+                .parseSignedClaims(token)
+                .getPayload();
+    }
+
+    public boolean validateToken(String token) {
+        try {
+            parseToken(token);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public Long getUserId(String token) {
+        Claims claims = parseToken(token);
+        return claims.get("userId", Long.class);
+    }
+
+    public String getAccount(String token) {
+        Claims claims = parseToken(token);
+        return claims.get("account", String.class);
+    }
+    public String getUsername(String token) {
+        Claims claims = parseToken(token);
+        return claims.get("username", String.class);
+    }
+
+    public String getRole(String token) {
+        Claims claims = parseToken(token);
+        return claims.get("role", String.class);
+    }
+}

+ 31 - 0
src/main/java/space/anyi/serve/service/impl/UserDetailsServiceImpl.java

@@ -0,0 +1,31 @@
+package space.anyi.serve.service.impl;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import space.anyi.serve.entity.auth.JwtUserDetails;
+import space.anyi.serve.entity.user.User;
+import space.anyi.serve.service.UserService;
+
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+
+    private final UserService userService;
+
+    public UserDetailsServiceImpl(UserService userService) {
+        this.userService = userService;
+    }
+
+    @Override
+    public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {
+        User user = userService.lambdaQuery()
+                .eq(User::getAccount, account)
+                .eq(User::getEnable, 1)
+                .one();
+        if (user == null) {
+            throw new UsernameNotFoundException("账号或密码错误");
+        }
+        return new JwtUserDetails(user);
+    }
+}

+ 15 - 2
src/main/java/space/anyi/serve/service/impl/UserServiceImpl.java

@@ -4,7 +4,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
+import space.anyi.serve.entity.Response;
+import space.anyi.serve.entity.auth.JwtUserDetails;
+import space.anyi.serve.handler.security.JwtTokenProvider;
+import space.anyi.serve.entity.auth.AuthTokenVo;
 import space.anyi.serve.entity.user.User;
 import space.anyi.serve.mapper.UserMapper;
 import space.anyi.serve.service.UserService;
@@ -22,6 +29,13 @@ import java.util.Objects;
 @Service("userService")
 public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
 
+    private final PasswordEncoder passwordEncoder;
+
+
+    public UserServiceImpl(PasswordEncoder passwordEncoder) {
+        this.passwordEncoder = passwordEncoder;
+    }
+
     /**
      * 通过ID查询单条数据
      *
@@ -65,7 +79,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements Use
     @Override
     public Boolean updatePassword(User user, String oldPassword) {
         User user1 = getById(user.getId());
-        if (!oldPassword.equals(user1.getPassword())) {
+        if (!passwordEncoder.matches(oldPassword, user1.getPassword())) {
             return false;
         }
         return update(user);
@@ -93,7 +107,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements Use
         LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<User>()
                 .eq(User::getId, user.getId())
                 .set(Objects.nonNull(user.getAccount()),User::getAccount, user.getAccount())
-                .set(Objects.nonNull(user.getPassword()),User::getPassword,user.getPassword())
                 .set(Objects.nonNull(user.getUsername()),User::getUsername, user.getUsername())
                 .set(Objects.nonNull(user.getAvatar()), User::getAvatar,user.getAvatar())
                 .set(Objects.nonNull(user.getRole()),User::getRole, user.getRole())