commit 62b271798ae76bc8232e2c17b381bb2f35435da6 Author: xiang Date: Sun Aug 24 01:01:35 2025 +0800 feat:密码模式登陆v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8cc9e56 --- /dev/null +++ b/pom.xml @@ -0,0 +1,69 @@ + + + + com.xiang + xservice-basic + 2.0-SNAPSHOT + + pom + + xs-api + xs-server + xs-service + + + 4.0.0 + + com.xiang + xservice-auth-center + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.security + spring-security-oauth2-authorization-server + 0.4.0 + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + + org.springframework.security + spring-security-oauth2-jose + 5.7.11 + + + + com.xiang + xservice-common + 2.0-SNAPSHOT + + + + com.xiang + xservice-mysql-starter + 2.0 + + + + \ No newline at end of file diff --git a/xs-api/pom.xml b/xs-api/pom.xml new file mode 100644 index 0000000..8a59dd9 --- /dev/null +++ b/xs-api/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.xiang + xservice-auth-center + 1.0-SNAPSHOT + + + xs-api + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/req/LoginRequest.java b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/req/LoginRequest.java new file mode 100644 index 0000000..6b6f501 --- /dev/null +++ b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/req/LoginRequest.java @@ -0,0 +1,16 @@ +package com.xiang.xservice.auth.api.dto.req; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LoginRequest { + + private String username; + + private String password; +} diff --git a/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/LoginResp.java b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/LoginResp.java new file mode 100644 index 0000000..0ad934f --- /dev/null +++ b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/LoginResp.java @@ -0,0 +1,15 @@ +package com.xiang.xservice.auth.api.dto.resp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LoginResp { + + private String username; + + private String token; +} diff --git a/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/UserResp.java b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/UserResp.java new file mode 100644 index 0000000..30195f1 --- /dev/null +++ b/xs-api/src/main/java/com/xiang/xservice/auth/api/dto/resp/UserResp.java @@ -0,0 +1,58 @@ +package com.xiang.xservice.auth.api.dto.resp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserResp { + + /** + * 用户名(昵称) + */ + private String name; + + /** + * 账号 + */ + private String username; + + /** + * 邮箱 + */ + private String email; + + /** + * 手机号 + */ + private String phone; + + /** + * 头像 + */ + private String avatar; + + /** + * 最后登陆ip + */ + private String loginIp; + + /** + * 最后登陆时间 + */ + private LocalDateTime loginDate; + + /** + * 状态(0:禁用, 1:启用) + */ + private Integer status; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; +} diff --git a/xs-server/pom.xml b/xs-server/pom.xml new file mode 100644 index 0000000..2f8ce2a --- /dev/null +++ b/xs-server/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + com.xiang + xservice-auth-center + 1.0-SNAPSHOT + + + xs-server + + + 17 + 17 + UTF-8 + + + + + com.xiang + xs-service + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/xs-server/src/main/java/com/xiang/AuthApplication.java b/xs-server/src/main/java/com/xiang/AuthApplication.java new file mode 100644 index 0000000..b7a6143 --- /dev/null +++ b/xs-server/src/main/java/com/xiang/AuthApplication.java @@ -0,0 +1,11 @@ +package com.xiang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AuthApplication { + public static void main(String[] args) { + SpringApplication.run(AuthApplication.class, args); + } +} \ No newline at end of file diff --git a/xs-server/src/main/java/com/xiang/xservice/auth/server/controller/TokenController.java b/xs-server/src/main/java/com/xiang/xservice/auth/server/controller/TokenController.java new file mode 100644 index 0000000..22479d3 --- /dev/null +++ b/xs-server/src/main/java/com/xiang/xservice/auth/server/controller/TokenController.java @@ -0,0 +1,25 @@ +package com.xiang.xservice.auth.server.controller; + +import com.xiang.xservice.auth.api.dto.req.LoginRequest; +import com.xiang.xservice.auth.api.dto.resp.LoginResp; +import com.xiang.xservice.auth.service.service.XUserService; +import com.xiang.xservice.basic.common.resp.Result; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +@RestController +@RequiredArgsConstructor +public class TokenController { + + private final XUserService userService; + + @PostMapping("/public/auth/login") + public Result login(@RequestBody @NotNull(message = "请求参数不能为空") @Valid LoginRequest request) { + return Result.success("操作成功", userService.login(request)); + } +} diff --git a/xs-server/src/main/resources/application-local.yml b/xs-server/src/main/resources/application-local.yml new file mode 100644 index 0000000..c3593ab --- /dev/null +++ b/xs-server/src/main/resources/application-local.yml @@ -0,0 +1,23 @@ +spring: + datasource: + dynamic: + primary: master + datasource: + master: + url: jdbc:mysql://rm-bp1j371yx9d9894ewbo.mysql.rds.aliyuncs.com:3306/xservice-user?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true + username: root + password: xb#UWqnhH24&XpX + driver-class-name: com.mysql.cj.jdbc.Driver + sshConnect: false + redis: + host: r-bp1dqqbzlfw04fldp3pd.redis.rds.aliyuncs.com + port: 6379 + password: Admin@123 # 如果无密码可以省略 + database: 0 + timeout: 5000 + lettuce: + pool: + max-active: 8 + max-idle: 8 + min-idle: 0 + max-wait: 1000 \ No newline at end of file diff --git a/xs-server/src/main/resources/application.yml b/xs-server/src/main/resources/application.yml new file mode 100644 index 0000000..995f841 --- /dev/null +++ b/xs-server/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 38011 +spring: + profiles: + active: local + +mybatis: + mapper-locations: + - classpath*:mapper/*/*.xml + configuration: + map-underscore-to-camel-case: true \ No newline at end of file diff --git a/xs-service/pom.xml b/xs-service/pom.xml new file mode 100644 index 0000000..9cfb6ea --- /dev/null +++ b/xs-service/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + com.xiang + xservice-auth-center + 1.0-SNAPSHOT + + + xs-service + + + 17 + 17 + UTF-8 + + + + + com.xiang + xs-api + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/config/AuthorizationServerConfig.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/config/AuthorizationServerConfig.java new file mode 100644 index 0000000..e437f0c --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/config/AuthorizationServerConfig.java @@ -0,0 +1,104 @@ +package com.xiang.xservice.auth.service.config; + +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.proc.SecurityContext; +import com.xiang.xservice.basic.utils.JwkUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; +import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; +import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; +import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; +import org.springframework.security.web.SecurityFilterChain; + + +import java.util.UUID; + +@Configuration(proxyBeanMethods = false) +public class AuthorizationServerConfig { + + @Bean + @Order(1) + public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) + throws Exception { + OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); + return http.build(); + } + + @Bean + @Order(2) + public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { + http + .csrf().disable() // 禁用 CSRF + .authorizeRequests(authorizeRequests -> authorizeRequests + .antMatchers("/public/auth/login").permitAll() + .anyRequest().authenticated() + ) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + + return http.build(); + } + + @Bean + public RegisteredClientRepository registeredClientRepository() { + RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) + .clientId("messaging-client") + .clientSecret("{noop}secret") // 演示用,生产请加密 + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD) + .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) + .scope("message.read") + .scope("message.write") + .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) + .build(); + + return new InMemoryRegisteredClientRepository(registeredClient); + } + + @Bean + public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, + PasswordEncoder passwordEncoder) { + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + provider.setUserDetailsService(userDetailsService); + provider.setPasswordEncoder(passwordEncoder); + return new ProviderManager(provider); + } + + + @Bean + public JWKSource jwkSource() { + RSAKey rsaKey = JwkUtils.generateRsa(); + JWKSet jwkSet = new JWKSet(rsaKey); + return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); + } + + @Bean + public JwtEncoder jwtEncoder(JWKSource jwkSource) { + return new NimbusJwtEncoder(jwkSource); + } + + @Bean + public AuthorizationServerSettings authorizationServerSettings() { + return AuthorizationServerSettings.builder() + .issuer("http://auth-server:9000") // 你的认证服务器地址 + .build(); + } +} + diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/config/SecurityConfig.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/config/SecurityConfig.java new file mode 100644 index 0000000..7e1da3c --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/config/SecurityConfig.java @@ -0,0 +1,39 @@ +package com.xiang.xservice.auth.service.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + // 关闭 csrf(如果是前后端分离推荐关闭) + .csrf().disable() + + // 授权规则 + .authorizeHttpRequests(auth -> auth + .antMatchers("/public/auth/login", "/public/auth/register").permitAll() // 登录注册放行 + .anyRequest().authenticated() // 其他请求需要认证 + ) + // 登出配置 + .logout(Customizer.withDefaults()); + + return http.build(); + } + + // 密码加密器 + @Bean + public PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/entity/XUser.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/entity/XUser.java new file mode 100644 index 0000000..22effa5 --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/entity/XUser.java @@ -0,0 +1,93 @@ +package com.xiang.xservice.auth.service.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class XUser implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private Long id; + + /** + * 用户名(昵称) + */ + private String name; + + /** + * 账号 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 邮箱 + */ + private String email; + + /** + * 手机号 + */ + private String phone; + + /** + * 头像 + */ + private String avatar; + + /** + * 最后登陆ip + */ + private String loginIp; + + /** + * 最后登陆时间 + */ + private LocalDateTime loginDate; + + /** + * 状态(0:禁用, 1:启用) + */ + private Integer status; + + /** + * 删除标识(0:未删除 1:已删除) + */ + private Integer delFlag; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/repository/mapper/XUserMapper.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/repository/mapper/XUserMapper.java new file mode 100644 index 0000000..351bf0b --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/repository/mapper/XUserMapper.java @@ -0,0 +1,12 @@ +package com.xiang.xservice.auth.service.repository.mapper; + +import com.xiang.xservice.auth.service.entity.XUser; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Repository +@Mapper +public interface XUserMapper { + + XUser selectByUsername(String username); +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CustomUserDetailsService.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CustomUserDetailsService.java new file mode 100644 index 0000000..124c057 --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/CustomUserDetailsService.java @@ -0,0 +1,34 @@ +package com.xiang.xservice.auth.service.service; + +import com.xiang.xservice.auth.service.entity.XUser; +import com.xiang.xservice.auth.service.repository.mapper.XUserMapper; +import lombok.RequiredArgsConstructor; +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 java.util.Objects; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + + private final XUserMapper userMapper; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + XUser user = userMapper.selectByUsername(username); + if (Objects.isNull(user)) { + throw new RuntimeException("用户不存在!"); + } + + return org.springframework.security.core.userdetails.User + .withUsername(user.getUsername()) + .password(user.getPassword()) // 已经加密的 + .authorities("admin") +// .roles(user.getRole()) // 角色 + .build(); + } +} + diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/XUserService.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/XUserService.java new file mode 100644 index 0000000..826351c --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/XUserService.java @@ -0,0 +1,14 @@ +package com.xiang.xservice.auth.service.service; + +import com.xiang.xservice.auth.api.dto.req.LoginRequest; +import com.xiang.xservice.auth.api.dto.resp.LoginResp; +import com.xiang.xservice.auth.api.dto.resp.UserResp; +import com.xiang.xservice.mysql.annotation.DynamicDataSource; + +public interface XUserService { + + @DynamicDataSource("master") + LoginResp login(LoginRequest request); + @DynamicDataSource("master") + UserResp getUserByUsername(String username); +} diff --git a/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/XUserServiceImpl.java b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/XUserServiceImpl.java new file mode 100644 index 0000000..316a425 --- /dev/null +++ b/xs-service/src/main/java/com/xiang/xservice/auth/service/service/impl/XUserServiceImpl.java @@ -0,0 +1,84 @@ +package com.xiang.xservice.auth.service.service.impl; + +import com.xiang.xservice.auth.api.dto.req.LoginRequest; +import com.xiang.xservice.auth.api.dto.resp.LoginResp; +import com.xiang.xservice.auth.api.dto.resp.UserResp; +import com.xiang.xservice.auth.service.entity.XUser; +import com.xiang.xservice.auth.service.repository.mapper.XUserMapper; +import com.xiang.xservice.auth.service.service.XUserService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.JwtClaimsSet; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.JwtEncoderParameters; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Objects; + +@Slf4j +@Service +@RequiredArgsConstructor +public class XUserServiceImpl implements XUserService { + + private final JwtEncoder jwtEncoder; + private final XUserMapper userMapper; + private final AuthenticationManager authenticationManager; + + @Override + public LoginResp login(LoginRequest request) { + try { + Authentication authenticate = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()) + ); + SecurityContextHolder.getContext().setAuthentication(authenticate); + } catch (Exception e) { + log.error(e.getMessage()); + throw new RuntimeException(e.getMessage()); + } + + // 生成 token + Instant now = Instant.now(); + + // todo 1. 构建 claims + JwtClaimsSet claims = JwtClaimsSet.builder() + // 对应 ProviderSettings.issuer + .issuedAt(now) + .expiresAt(now.plus(1, ChronoUnit.HOURS)) + // 自定义 scope + .claim("username", request.getUsername()) + .build(); + + // 2. 编码生成 token + String token = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue(); + LoginResp loginResp = new LoginResp(); + loginResp.setToken(token); + loginResp.setUsername(request.getUsername()); + return loginResp; + } + + @Override + public UserResp getUserByUsername(String username) { + XUser user = userMapper.selectByUsername(username); + if (Objects.isNull(user)) { + return null; + } + + UserResp userResp = new UserResp(); + userResp.setName(user.getName()); + userResp.setUsername(user.getUsername()); + userResp.setEmail(user.getEmail()); + userResp.setPhone(user.getPhone()); + userResp.setAvatar(user.getAvatar()); + userResp.setLoginIp(user.getLoginIp()); + userResp.setLoginDate(user.getLoginDate()); + userResp.setStatus(user.getStatus()); + userResp.setUpdateTime(user.getUpdateTime()); + return userResp; + } +} diff --git a/xs-service/src/main/resources/mapper/user/XUserMapper.xml b/xs-service/src/main/resources/mapper/user/XUserMapper.xml new file mode 100644 index 0000000..15bf3d1 --- /dev/null +++ b/xs-service/src/main/resources/mapper/user/XUserMapper.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + id, + name, + username, + password, + email, + phone, + avatar, + login_ip, + login_date, + status, + del_flag, + create_by, + create_time, + update_by, + update_time + + + + INSERT INTO x_user + + + name, + + + username, + + + password, + + + email, + + + phone, + + + avatar, + + + login_ip, + + + login_date, + + + del_flag, + + + status, + + + create_by, + + + create_time, + + + update_by, + + + update_time + + + + + #{name}, + + + #{username}, + + + #{password}, + + + #{email}, + + + #{phone}, + + + #{avatar}, + + + #{loginIp}, + + + #{loginDate}, + + + #{delFlag}, + + + #{status}, + + + #{createBy}, + + + #{createTime}, + + + #{updateBy}, + + + #{updateTime} + + + + + + update x_user set del_flag = 1 where id = #{id} + + + + UPDATE x_user + + name = #{name}, + username = #{username}, + password = #{password}, + email = #{email}, + phone = #{phone}, + avatar = #{avatar}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + del_flag = #{delFlag}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime} + + WHERE id = #{id} + + + + + \ No newline at end of file