feat: 自定义登录页
This commit is contained in:
parent
4efb99a655
commit
58e0b5f4d1
|
@ -1521,4 +1521,226 @@ Thymeleaf 是一种现代化的 Java 模板引擎,广泛用于生成 HTML、XM
|
||||||
<div th:errors="*{username}">Error</div>
|
<div th:errors="*{username}">Error</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
如果验证失败,错误消息将显示在 `<div>` 中。如果没有错误,它会显示默认的 "Error" 文本。
|
如果验证失败,错误消息将显示在 `<div>` 中。如果没有错误,它会显示默认的 "Error" 文本。
|
||||||
|
|
||||||
|
## SpringSecurity
|
||||||
|
|
||||||
|
### 密码转换器(Password Encoder)
|
||||||
|
|
||||||
|
Spring Security 提供了多种密码转换器(Password Encoder),这些转换器用于对用户密码进行加密和验证。常见的密码转换器包括:
|
||||||
|
|
||||||
|
1. **BCryptPasswordEncoder**:
|
||||||
|
|
||||||
|
- 使用 **BCrypt** 算法对密码进行加密。
|
||||||
|
|
||||||
|
- 是最常用的密码加密方案,具有强大的加密性,并且支持自动加盐(salt),防止暴力破解攻击。
|
||||||
|
|
||||||
|
- 示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **NoOpPasswordEncoder**:
|
||||||
|
|
||||||
|
- 不对密码进行加密,直接返回明文密码。
|
||||||
|
|
||||||
|
- 主要用于开发和测试环境,**不推荐在生产环境中使用**。
|
||||||
|
|
||||||
|
- 示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return NoOpPasswordEncoder.getInstance();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Pbkdf2PasswordEncoder**:
|
||||||
|
|
||||||
|
- 使用 **PBKDF2** 算法进行密码加密。
|
||||||
|
|
||||||
|
- 提供较强的安全性,并且支持对密码进行哈希。
|
||||||
|
|
||||||
|
- 示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new Pbkdf2PasswordEncoder();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Argon2PasswordEncoder**:
|
||||||
|
|
||||||
|
- 使用 **Argon2** 算法对密码进行加密。
|
||||||
|
|
||||||
|
- Argon2 是目前被认为最强的密码哈希算法,支持内存密集型计算,从而防止硬件加速破解。
|
||||||
|
|
||||||
|
- 示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new Argon2PasswordEncoder();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **SCryptPasswordEncoder**:
|
||||||
|
|
||||||
|
- 使用 **SCrypt** 算法进行密码加密。
|
||||||
|
|
||||||
|
- SCrypt 是另一种内存密集型的密码加密算法,与 Argon2 类似,旨在防止硬件加速破解。
|
||||||
|
|
||||||
|
- 示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new SCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **MessageDigestPasswordEncoder** (已废弃):
|
||||||
|
|
||||||
|
- 基于 **MessageDigest** 算法进行加密(如 SHA-1、SHA-256 等)。
|
||||||
|
- 由于缺乏盐和密钥加密机制,已被其他更强的加密方式所替代。
|
||||||
|
|
||||||
|
> 选择密码转换器的建议:
|
||||||
|
>
|
||||||
|
> - 在现代应用中,推荐使用 **BCryptPasswordEncoder** 或 **Argon2PasswordEncoder**,这两种算法提供了强大的加密性。
|
||||||
|
> - **Pbkdf2PasswordEncoder** 和 **SCryptPasswordEncoder** 也可以作为备选方案,尤其是当你希望加密算法能够承受更多资源密集型攻击时。
|
||||||
|
> - **NoOpPasswordEncoder** 仅限于开发和测试环境。
|
||||||
|
|
||||||
|
### 访问主页
|
||||||
|
|
||||||
|
需要使用`http://localhost:8080/index`来访问主页,可以在配置中配置,访问根路径直接跳转
|
||||||
|
|
||||||
|
```java
|
||||||
|
@RequestMapping
|
||||||
|
@Controller
|
||||||
|
public class HomeController {
|
||||||
|
|
||||||
|
@Operation(summary = "主页内容")
|
||||||
|
@GetMapping("index")
|
||||||
|
public String index() {
|
||||||
|
return "index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "订单内容")
|
||||||
|
@GetMapping("order")
|
||||||
|
public String order() {
|
||||||
|
return "order";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "login")
|
||||||
|
@GetMapping("login")
|
||||||
|
public String login() {
|
||||||
|
return "login";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
在配置中
|
||||||
|
|
||||||
|
```java
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
|
registry.addViewController("/")
|
||||||
|
// .setViewName("forward:/index") //两种方式写法
|
||||||
|
.setViewName("index");
|
||||||
|
registry.addViewController("/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义登录
|
||||||
|
|
||||||
|
```java
|
||||||
|
package cn.bunny.springdemo.configuration;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.entity.AdminUser;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new SCryptPasswordEncoder(4, 8, 1, 8, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用内存方式
|
||||||
|
*
|
||||||
|
* @param encoder 密码加密器
|
||||||
|
* @return 基于内存的用户
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
|
||||||
|
ArrayList<UserDetails> userDetails = new ArrayList<>();
|
||||||
|
userDetails.add(new AdminUser("admin", encoder.encode("admin"), true));
|
||||||
|
userDetails.add(new AdminUser("bunny", encoder.encode("password"), true));
|
||||||
|
|
||||||
|
return new InMemoryUserDetailsManager(userDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 使用数据库方式
|
||||||
|
// *
|
||||||
|
// * @param userService 获取用户数据(如数据库)
|
||||||
|
// * @return 基于数据库的用户
|
||||||
|
// */
|
||||||
|
// @Bean
|
||||||
|
// public UserDetailsService userDetailsService(UserService userService) {
|
||||||
|
// return username -> {
|
||||||
|
// AdminUser adminUser = userService.getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getUsername, userService));
|
||||||
|
// if (adminUser != null) {
|
||||||
|
// return adminUser;
|
||||||
|
// }
|
||||||
|
// throw new UsernameNotFoundException("未找到 AdminUser");
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {
|
||||||
|
return security
|
||||||
|
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
|
||||||
|
authorizationManagerRequestMatcherRegistry
|
||||||
|
.requestMatchers("/order").hasRole("USER")// 请求需要含有USER角色
|
||||||
|
.requestMatchers("/", "/index", "/login", "/images/**").permitAll()
|
||||||
|
)
|
||||||
|
/* 自定义登录页面 */
|
||||||
|
// .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)// 默认的登录页会自动启用,无需额外配置
|
||||||
|
.formLogin(formLoginConfigurer -> formLoginConfigurer
|
||||||
|
.loginPage("/login")
|
||||||
|
// .loginProcessingUrl("/authenticate")
|
||||||
|
.usernameParameter("username")// 自定义用户名名称
|
||||||
|
.usernameParameter("password")// 自定义密码名称
|
||||||
|
.defaultSuccessUrl("/index")// 登录成功后默认跳转页面
|
||||||
|
// .defaultSuccessUrl("/index", true)// 登录成功后默认跳转页面,如果用户之前访问页面也需要强制跳转到 /index 可以传递第二个参数
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -17,7 +17,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
||||||
<mysql.version>8.0.30</mysql.version>
|
<mysql.version>8.0.33</mysql.version>
|
||||||
<HikariCP.version>5.1.0</HikariCP.version>
|
<HikariCP.version>5.1.0</HikariCP.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- lombok -->
|
<!-- lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|
|
@ -30,3 +30,63 @@
|
||||||
11:13:44:041 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
11:13:44:041 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
||||||
11:13:44:042 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
11:13:44:042 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
||||||
11:13:44:062 INFO 12616 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.888 seconds (process running for 1.466)
|
11:13:44:062 INFO 12616 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.888 seconds (process running for 1.466)
|
||||||
|
12:56:08:799 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 10508 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:56:08:802 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:56:09:855 INFO 10508 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:56:09:868 INFO 10508 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:56:10:093 INFO 10508 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:56:10:240 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.717 seconds (process running for 2.253)
|
||||||
|
12:56:30:906 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 21060 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:56:30:909 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:56:31:936 INFO 21060 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:56:31:950 INFO 21060 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:56:32:175 INFO 21060 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:56:32:317 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.675 seconds (process running for 2.201)
|
||||||
|
12:56:49:178 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 19580 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:56:49:181 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:56:50:206 INFO 19580 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:56:50:220 INFO 19580 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:56:50:449 INFO 19580 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:56:50:598 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.688 seconds (process running for 2.241)
|
||||||
|
12:57:19:701 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 12696 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:57:19:704 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:57:20:735 INFO 12696 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:57:20:750 INFO 12696 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:57:20:979 INFO 12696 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:57:21:127 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.708 seconds (process running for 2.258)
|
||||||
|
12:57:45:076 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 9352 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:57:45:079 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:57:46:202 INFO 9352 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:57:46:219 INFO 9352 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:57:46:462 INFO 9352 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:57:46:630 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.858 seconds (process running for 2.69)
|
||||||
|
12:58:16:559 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 1652 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:58:16:563 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:58:17:571 INFO 1652 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:58:17:585 INFO 1652 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:58:17:813 INFO 1652 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:58:17:955 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.689 seconds (process running for 2.236)
|
||||||
|
12:58:31:856 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 4352 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:58:31:860 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:58:42:935 INFO 4352 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:58:42:951 INFO 4352 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:58:43:193 INFO 4352 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:58:43:364 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 11.813 seconds (process running for 12.431)
|
||||||
|
12:58:47:757 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 22540 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:58:47:760 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:58:53:578 INFO 22540 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:58:53:593 INFO 22540 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:58:53:835 INFO 22540 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:58:54:003 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 6.548 seconds (process running for 7.169)
|
||||||
|
12:59:00:364 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 21332 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
12:59:00:367 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
12:59:01:498 INFO 21332 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
12:59:01:514 INFO 21332 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
12:59:01:752 INFO 21332 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
12:59:01:920 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.851 seconds (process running for 2.456)
|
||||||
|
13:02:06:411 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 13172 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
||||||
|
13:02:06:416 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
||||||
|
13:02:07:458 INFO 13172 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
||||||
|
13:02:07:471 INFO 13172 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
||||||
|
13:02:07:695 INFO 13172 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
||||||
|
13:02:07:837 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.696 seconds (process running for 2.265)
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
<fastjson2.version>2.0.47</fastjson2.version>
|
<fastjson2.version>2.0.47</fastjson2.version>
|
||||||
<version>${junit.version}</version>
|
<version>${junit.version}</version>
|
||||||
|
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
||||||
|
<mysql.version>8.0.33</mysql.version>
|
||||||
|
<HikariCP.version>5.1.0</HikariCP.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -45,6 +48,17 @@
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-test</artifactId>
|
<artifactId>spring-security-test</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
<version>1.70</version> <!-- 请使用最新版本 -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcpg-jdk15on</artifactId>
|
||||||
|
<version>1.70</version> <!-- 请使用最新版本 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- devtools -->
|
<!-- devtools -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -92,7 +106,24 @@
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.8.27</version>
|
<version>5.8.27</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- mybatis-plus -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- mysql -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>${mysql.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- mysql连接池 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>${HikariCP.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package cn.bunny.springdemo.configuration;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.entity.AdminUser;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new SCryptPasswordEncoder(4, 8, 1, 8, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用内存方式
|
||||||
|
*
|
||||||
|
* @param encoder 密码加密器
|
||||||
|
* @return 基于内存的用户
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
|
||||||
|
ArrayList<UserDetails> userDetails = new ArrayList<>();
|
||||||
|
userDetails.add(new AdminUser("admin", encoder.encode("admin"), true));
|
||||||
|
userDetails.add(new AdminUser("bunny", encoder.encode("password"), true));
|
||||||
|
|
||||||
|
return new InMemoryUserDetailsManager(userDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 使用数据库方式
|
||||||
|
// *
|
||||||
|
// * @param userService 获取用户数据(如数据库)
|
||||||
|
// * @return 基于数据库的用户
|
||||||
|
// */
|
||||||
|
// @Bean
|
||||||
|
// public UserDetailsService userDetailsService(UserService userService) {
|
||||||
|
// return username -> {
|
||||||
|
// AdminUser adminUser = userService.getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getUsername, userService));
|
||||||
|
// if (adminUser != null) {
|
||||||
|
// return adminUser;
|
||||||
|
// }
|
||||||
|
// throw new UsernameNotFoundException("未找到 AdminUser");
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {
|
||||||
|
return security
|
||||||
|
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
|
||||||
|
authorizationManagerRequestMatcherRegistry
|
||||||
|
.requestMatchers("/order").hasRole("USER")// 请求需要含有USER角色
|
||||||
|
.requestMatchers("/", "/index", "/login", "/images/**").permitAll()
|
||||||
|
)
|
||||||
|
/* 自定义登录页面 */
|
||||||
|
// .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)// 默认的登录页会自动启用,无需额外配置
|
||||||
|
.formLogin(formLoginConfigurer -> formLoginConfigurer
|
||||||
|
.loginPage("/login")
|
||||||
|
// .loginProcessingUrl("/authenticate")
|
||||||
|
.usernameParameter("username")// 自定义用户名名称
|
||||||
|
.usernameParameter("password")// 自定义密码名称
|
||||||
|
.defaultSuccessUrl("/index")// 登录成功后默认跳转页面
|
||||||
|
// .defaultSuccessUrl("/index", true)// 登录成功后默认跳转页面,如果用户之前访问页面也需要强制跳转到 /index 可以传递第二个参数
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.bunny.springdemo.configuration;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
|
registry.addViewController("/")
|
||||||
|
// .setViewName("forward:/index") //两种方式写法
|
||||||
|
.setViewName("index");
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,4 +14,16 @@ public class HomeController {
|
||||||
public String index() {
|
public String index() {
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "订单内容")
|
||||||
|
@GetMapping("order")
|
||||||
|
public String order() {
|
||||||
|
return "order";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "login")
|
||||||
|
@GetMapping("login")
|
||||||
|
public String login() {
|
||||||
|
return "login";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cn.bunny.springdemo.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(name = "BaseEntity", title = "基础信息字段", description = "基础信息字段")
|
||||||
|
public class BaseEntity implements Serializable {
|
||||||
|
|
||||||
|
@Schema(name = "id", title = "唯一标识")
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(name = "createTime", title = "创建时间")
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(name = "updateTime", title = "更新时间")
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
@Schema(name = "createUser", title = "创建用户")
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long createUser;
|
||||||
|
|
||||||
|
@Schema(name = "updateUser", title = "操作用户")
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long updateUser;
|
||||||
|
|
||||||
|
@Schema(name = "isDeleted", title = "是否被删除")
|
||||||
|
@TableLogic
|
||||||
|
private Boolean isDeleted;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.springdemo.dao;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@Schema(name = "BaseUserEntity", title = "基础信息字段包含用户信息", description = "基础信息字段包含用户信息")
|
||||||
|
public class BaseUserEntity extends BaseEntity {
|
||||||
|
|
||||||
|
@Schema(name = "username", title = "用户名")
|
||||||
|
private String createUsername;
|
||||||
|
|
||||||
|
@Schema(name = "nickname", title = "昵称")
|
||||||
|
private String updateUsername;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package cn.bunny.springdemo.dao.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Schema(name = "BillDto对象", title = "账单信息查询内容", description = "账单信息查询内容")
|
||||||
|
public class BillDto {
|
||||||
|
|
||||||
|
@Schema(name = "userId", title = "绑定的用户id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(name = "amount", title = "金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Schema(name = "categoryIds", title = "类别分类")
|
||||||
|
private List<Long> categoryIds;
|
||||||
|
|
||||||
|
@Schema(name = "username", title = "类型:1 - 收入,-1 - 支出")
|
||||||
|
private Byte type;
|
||||||
|
|
||||||
|
@Schema(name = "description", title = "描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(name = "startDate", title = "开始交易日期")
|
||||||
|
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDate startDate;
|
||||||
|
|
||||||
|
@Schema(name = "endDate", title = "结束交易日期")
|
||||||
|
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDate endDate;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cn.bunny.springdemo.dao.entity;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.BaseEntity;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 管理员用户信息
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Bunny
|
||||||
|
* @since 2024-06-26
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("sys_user")
|
||||||
|
@Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息")
|
||||||
|
public class AdminUser extends BaseEntity implements UserDetails {
|
||||||
|
|
||||||
|
@Schema(name = "username", title = "用户名")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Schema(name = "password", title = "密码")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Schema(name = "status", title = "状态", description = "1:禁用 0:正常")
|
||||||
|
private Boolean status;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cn.bunny.springdemo.dao.entity;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.BaseEntity;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 账单信息
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Bunny
|
||||||
|
* @since 2024-11-07
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("t_bill")
|
||||||
|
@Schema(name = "Bill对象", title = "账单信息", description = "账单信息")
|
||||||
|
public class Bill extends BaseEntity {
|
||||||
|
|
||||||
|
@Schema(name = "username", title = "类型:1 - 收入,-1 - 支出")
|
||||||
|
private Byte type;
|
||||||
|
|
||||||
|
@Schema(name = "userId", title = "绑定的用户id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(name = "amount", title = "金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Schema(name = "description", title = "描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(name = "transactionDate", title = "交易日期")
|
||||||
|
private LocalDateTime transactionDate;
|
||||||
|
|
||||||
|
@Schema(name = "categoryId", title = "类别id")
|
||||||
|
private Long categoryId;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cn.bunny.springdemo.mapper;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.entity.AdminUser;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 用户信息 Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Bunny
|
||||||
|
* @since 2024-09-26
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface UserMapper extends BaseMapper<AdminUser> {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.bunny.springdemo.services;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.entity.AdminUser;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 用户信息 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Bunny
|
||||||
|
* @since 2024-09-26
|
||||||
|
*/
|
||||||
|
public interface UserService extends IService<AdminUser> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.bunny.springdemo.services.impl;
|
||||||
|
|
||||||
|
import cn.bunny.springdemo.dao.entity.AdminUser;
|
||||||
|
import cn.bunny.springdemo.mapper.UserMapper;
|
||||||
|
import cn.bunny.springdemo.services.UserService;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息 服务实现类
|
||||||
|
*
|
||||||
|
* @author Bunny
|
||||||
|
* @since 2024-09-26
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserService {
|
||||||
|
|
||||||
|
}
|
|
@ -8,12 +8,12 @@ spring:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 6MB
|
max-file-size: 6MB
|
||||||
|
|
||||||
# datasource:
|
datasource:
|
||||||
# type: com.zaxxer.hikari.HikariDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
# url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
||||||
# username: ${bunny.master.username}
|
username: ${bunny.master.username}
|
||||||
# password: ${bunny.master.password}
|
password: ${bunny.master.password}
|
||||||
|
|
||||||
jackson:
|
jackson:
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>边框流动效果的login页面 www.bootstrapmb.com</title>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<meta content="ie=edge" http-equiv="X-UA-Compatible"/>
|
||||||
|
<style media="screen">
|
||||||
|
* {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #0c0116
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
position: relative;
|
||||||
|
padding: 60px 15px;
|
||||||
|
width: 270px;
|
||||||
|
height: 350px;
|
||||||
|
background: #0c0116;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 0 10px 0 #747772;
|
||||||
|
border-radius: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inner {
|
||||||
|
position: absolute;
|
||||||
|
height: 98%;
|
||||||
|
width: 98%;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
background: #0c0116;
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inner h2 {
|
||||||
|
font-size: 25px;
|
||||||
|
color: #d7a3d7;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 35px
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
display: block;
|
||||||
|
padding: 12px 15px;
|
||||||
|
width: 100%;
|
||||||
|
left: 50%;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
border: 1.5px solid #6d5779;
|
||||||
|
outline: 0;
|
||||||
|
background: #19052c;
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
margin-top: 40px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
outline: 0;
|
||||||
|
background: #800080;
|
||||||
|
border: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
border-radius: 10px;
|
||||||
|
transition: .4s
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background: #c907c9
|
||||||
|
}
|
||||||
|
|
||||||
|
.form span {
|
||||||
|
position: absolute;
|
||||||
|
height: 50%;
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.form span:nth-child(1) {
|
||||||
|
background: #ffda05;
|
||||||
|
top: 0;
|
||||||
|
left: -48%;
|
||||||
|
animation: 5s span1 infinite linear;
|
||||||
|
animation-delay: 1s
|
||||||
|
}
|
||||||
|
|
||||||
|
.form span:nth-child(2) {
|
||||||
|
background: #00a800;
|
||||||
|
bottom: 0;
|
||||||
|
right: -48%;
|
||||||
|
animation: 5s span2 infinite linear
|
||||||
|
}
|
||||||
|
|
||||||
|
.form span:nth-child(3) {
|
||||||
|
background: #800080;
|
||||||
|
right: -48%;
|
||||||
|
top: 0;
|
||||||
|
animation: 5s span3 infinite linear
|
||||||
|
}
|
||||||
|
|
||||||
|
.form span:nth-child(4) {
|
||||||
|
background: #f00;
|
||||||
|
bottom: 0;
|
||||||
|
right: -48%;
|
||||||
|
animation: 5s span4 infinite linear;
|
||||||
|
animation-delay: 1s
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes span1 {
|
||||||
|
0% {
|
||||||
|
top: -48%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
top: -48%;
|
||||||
|
left: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
top: 98%;
|
||||||
|
left: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
top: 98%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -48%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes span2 {
|
||||||
|
0% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
bottom: 98%;
|
||||||
|
right: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
bottom: 98%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes span3 {
|
||||||
|
0% {
|
||||||
|
top: -48%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
top: -48%;
|
||||||
|
left: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
top: 98%;
|
||||||
|
left: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
top: 98%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -48%;
|
||||||
|
left: -48%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes span4 {
|
||||||
|
0% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
bottom: 98%;
|
||||||
|
right: 98%
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
bottom: 98%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
bottom: -48%;
|
||||||
|
right: -48%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form class="form" method="post" th:action="@{/login}">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<div class="form-inner">
|
||||||
|
<h2>登录界面</h2>
|
||||||
|
<div class="content">
|
||||||
|
<label>
|
||||||
|
<input class="input" name="username" placeholder="用户名" type="text" value="admin"/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input class="input" name="password" placeholder="密码" type="password" value="admin"/>
|
||||||
|
</label>
|
||||||
|
<button class="btn">登录</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>订单内容</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>订单内容</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,13 +1,20 @@
|
||||||
package cn.bunny.springdemo;
|
package cn.bunny.springdemo;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class SpringDemoApplicationTests {
|
class SpringDemoApplicationTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
||||||
|
String s = passwordEncoder.encode("admin123");
|
||||||
|
System.out.println(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue