feat:密码模式登陆v1
This commit is contained in:
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -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
|
||||||
69
pom.xml
Normal file
69
pom.xml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-basic</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>xs-api</module>
|
||||||
|
<module>xs-server</module>
|
||||||
|
<module>xs-service</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-auth-center</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--spring security -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- Authorization Server -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-oauth2-authorization-server</artifactId>
|
||||||
|
<version>0.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- JWT (optional: for convenience) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||||
|
<version>5.7.11</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-common</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-mysql-starter</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
20
xs-api/pom.xml
Normal file
20
xs-api/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-auth-center</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>xs-api</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
28
xs-server/pom.xml
Normal file
28
xs-server/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-auth-center</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>xs-server</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xs-service</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
11
xs-server/src/main/java/com/xiang/AuthApplication.java
Normal file
11
xs-server/src/main/java/com/xiang/AuthApplication.java
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<LoginResp> login(@RequestBody @NotNull(message = "请求参数不能为空") @Valid LoginRequest request) {
|
||||||
|
return Result.success("操作成功", userService.login(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
23
xs-server/src/main/resources/application-local.yml
Normal file
23
xs-server/src/main/resources/application-local.yml
Normal file
@@ -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
|
||||||
11
xs-server/src/main/resources/application.yml
Normal file
11
xs-server/src/main/resources/application.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
server:
|
||||||
|
port: 38011
|
||||||
|
spring:
|
||||||
|
profiles:
|
||||||
|
active: local
|
||||||
|
|
||||||
|
mybatis:
|
||||||
|
mapper-locations:
|
||||||
|
- classpath*:mapper/*/*.xml
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
28
xs-service/pom.xml
Normal file
28
xs-service/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xservice-auth-center</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>xs-service</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xs-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -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<SecurityContext> jwkSource() {
|
||||||
|
RSAKey rsaKey = JwkUtils.generateRsa();
|
||||||
|
JWKSet jwkSet = new JWKSet(rsaKey);
|
||||||
|
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
|
||||||
|
return new NimbusJwtEncoder(jwkSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthorizationServerSettings authorizationServerSettings() {
|
||||||
|
return AuthorizationServerSettings.builder()
|
||||||
|
.issuer("http://auth-server:9000") // 你的认证服务器地址
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
164
xs-service/src/main/resources/mapper/user/XUserMapper.xml
Normal file
164
xs-service/src/main/resources/mapper/user/XUserMapper.xml
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.xiang.xservice.auth.service.repository.mapper.XUserMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="com.xiang.xservice.auth.service.entity.XUser" >
|
||||||
|
<result column="id" property="id" />
|
||||||
|
<result column="name" property="name" />
|
||||||
|
<result column="username" property="username" />
|
||||||
|
<result column="password" property="password" />
|
||||||
|
<result column="email" property="email" />
|
||||||
|
<result column="phone" property="phone" />
|
||||||
|
<result column="avatar" property="avatar" />
|
||||||
|
<result column="login_ip" property="loginIp" />
|
||||||
|
<result column="login_date" property="loginDate" />
|
||||||
|
<result column="status" property="status"/>
|
||||||
|
<result column="del_flag" property="delFlag" />
|
||||||
|
<result column="create_by" property="createBy" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="update_by" property="updateBy" />
|
||||||
|
<result column="update_time" property="updateTime" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
avatar,
|
||||||
|
login_ip,
|
||||||
|
login_date,
|
||||||
|
status,
|
||||||
|
del_flag,
|
||||||
|
create_by,
|
||||||
|
create_time,
|
||||||
|
update_by,
|
||||||
|
update_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id" parameterType="com.xiang.xservice.auth.service.entity.XUser">
|
||||||
|
INSERT INTO x_user
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="null != name and '' != name">
|
||||||
|
name,
|
||||||
|
</if>
|
||||||
|
<if test="null != username and '' != username">
|
||||||
|
username,
|
||||||
|
</if>
|
||||||
|
<if test="null != password and '' != password">
|
||||||
|
password,
|
||||||
|
</if>
|
||||||
|
<if test="null != email and '' != email">
|
||||||
|
email,
|
||||||
|
</if>
|
||||||
|
<if test="null != phone and '' != phone">
|
||||||
|
phone,
|
||||||
|
</if>
|
||||||
|
<if test="null != avatar and '' != avatar">
|
||||||
|
avatar,
|
||||||
|
</if>
|
||||||
|
<if test="null != loginIp and '' != loginIp">
|
||||||
|
login_ip,
|
||||||
|
</if>
|
||||||
|
<if test="null != loginDate ">
|
||||||
|
login_date,
|
||||||
|
</if>
|
||||||
|
<if test="null != delFlag ">
|
||||||
|
del_flag,
|
||||||
|
</if>
|
||||||
|
<if test="null != status ">
|
||||||
|
status,
|
||||||
|
</if>
|
||||||
|
<if test="null != createBy and '' != createBy">
|
||||||
|
create_by,
|
||||||
|
</if>
|
||||||
|
<if test="null != createTime ">
|
||||||
|
create_time,
|
||||||
|
</if>
|
||||||
|
<if test="null != updateBy and '' != updateBy">
|
||||||
|
update_by,
|
||||||
|
</if>
|
||||||
|
<if test="null != updateTime ">
|
||||||
|
update_time
|
||||||
|
</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="null != name and '' != name">
|
||||||
|
#{name},
|
||||||
|
</if>
|
||||||
|
<if test="null != username and '' != username">
|
||||||
|
#{username},
|
||||||
|
</if>
|
||||||
|
<if test="null != password and '' != password">
|
||||||
|
#{password},
|
||||||
|
</if>
|
||||||
|
<if test="null != email and '' != email">
|
||||||
|
#{email},
|
||||||
|
</if>
|
||||||
|
<if test="null != phone and '' != phone">
|
||||||
|
#{phone},
|
||||||
|
</if>
|
||||||
|
<if test="null != avatar and '' != avatar">
|
||||||
|
#{avatar},
|
||||||
|
</if>
|
||||||
|
<if test="null != loginIp and '' != loginIp">
|
||||||
|
#{loginIp},
|
||||||
|
</if>
|
||||||
|
<if test="null != loginDate ">
|
||||||
|
#{loginDate},
|
||||||
|
</if>
|
||||||
|
<if test="null != delFlag ">
|
||||||
|
#{delFlag},
|
||||||
|
</if>
|
||||||
|
<if test="null != status ">
|
||||||
|
#{status},
|
||||||
|
</if>
|
||||||
|
<if test="null != createBy and '' != createBy">
|
||||||
|
#{createBy},
|
||||||
|
</if>
|
||||||
|
<if test="null != createTime ">
|
||||||
|
#{createTime},
|
||||||
|
</if>
|
||||||
|
<if test="null != updateBy and '' != updateBy">
|
||||||
|
#{updateBy},
|
||||||
|
</if>
|
||||||
|
<if test="null != updateTime ">
|
||||||
|
#{updateTime}
|
||||||
|
</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="delete" >
|
||||||
|
update x_user set del_flag = 1 where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.xiang.xservice.auth.service.entity.XUser">
|
||||||
|
UPDATE x_user
|
||||||
|
<set>
|
||||||
|
<if test="null != name and '' != name">name = #{name},</if>
|
||||||
|
<if test="null != username and '' != username">username = #{username},</if>
|
||||||
|
<if test="null != password and '' != password">password = #{password},</if>
|
||||||
|
<if test="null != email and '' != email">email = #{email},</if>
|
||||||
|
<if test="null != phone and '' != phone">phone = #{phone},</if>
|
||||||
|
<if test="null != avatar and '' != avatar">avatar = #{avatar},</if>
|
||||||
|
<if test="null != loginIp and '' != loginIp">login_ip = #{loginIp},</if>
|
||||||
|
<if test="null != loginDate ">login_date = #{loginDate},</if>
|
||||||
|
<if test="null != delFlag ">del_flag = #{delFlag},</if>
|
||||||
|
<if test="null != createBy and '' != createBy">create_by = #{createBy},</if>
|
||||||
|
<if test="null != createTime ">create_time = #{createTime},</if>
|
||||||
|
<if test="null != updateBy and '' != updateBy">update_by = #{updateBy},</if>
|
||||||
|
<if test="null != updateTime ">update_time = #{updateTime}</if>
|
||||||
|
</set>
|
||||||
|
WHERE id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<select id="selectByUsername" resultMap="BaseResultMap">
|
||||||
|
select <include refid="Base_Column_List"/>
|
||||||
|
from x_user
|
||||||
|
where username = #{username} and del_flag = 0 and status = 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user