login(@RequestBody LoginRequest loginRequest) {
- String username = loginRequest.getUsername();
- String password = loginRequest.getPassword();
-
- Authentication authenticationRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
-
- Authentication authenticationResponse = authenticationManager.authenticate(authenticationRequest);
- return Result.success(authenticationResponse);
+ @GetMapping("/login-page")
+ public String showLoginPage() {
+ return "login";
}
}
\ No newline at end of file
diff --git a/spring-security/step-1/src/main/java/com/spring/config/security/SecurityConfiguration.java b/spring-security/step-1/src/main/java/com/spring/security/SecurityConfiguration.java
similarity index 70%
rename from spring-security/step-1/src/main/java/com/spring/config/security/SecurityConfiguration.java
rename to spring-security/step-1/src/main/java/com/spring/security/SecurityConfiguration.java
index 1180368..b91b783 100644
--- a/spring-security/step-1/src/main/java/com/spring/config/security/SecurityConfiguration.java
+++ b/spring-security/step-1/src/main/java/com/spring/security/SecurityConfiguration.java
@@ -1,27 +1,17 @@
-package com.spring.config.security;
+package com.spring.security;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.User;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
-import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfiguration {
- @Bean
- SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http
- .authorizeHttpRequests(authorizeRequests ->
- authorizeRequests.anyRequest().authenticated()
- )
- ;
- return http.build();
- }
/**
* 添加内存用户
@@ -31,10 +21,15 @@ public class SecurityConfiguration {
@Bean
@ConditionalOnMissingBean(UserDetailsService.class)
InMemoryUserDetailsManager inMemoryUserDetailsManager(PasswordEncoder passwordEncoder) {
-
+ // 使用注入的密码加密器进行密码加密
String generatedPassword = passwordEncoder.encode("123456");
- return new InMemoryUserDetailsManager(User.withUsername("bunny")
- .password(generatedPassword).roles("USER").build());
+
+ // 创建用户
+ UserDetails userDetails1 = User.withUsername("bunny").password(generatedPassword).roles("USER").build();
+ UserDetails userDetails2 = User.withUsername("rabbit").password(generatedPassword).roles("USER").build();
+
+ // 返回内存中的用户
+ return new InMemoryUserDetailsManager(userDetails1, userDetails2);
}
/**
@@ -51,5 +46,8 @@ public class SecurityConfiguration {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
+
+ // 自定义实现密码加密器
+ // return new MD5PasswordEncoder();
}
}
diff --git a/spring-security/step-1/src/main/java/com/spring/security/SecurityWebConfiguration.java b/spring-security/step-1/src/main/java/com/spring/security/SecurityWebConfiguration.java
new file mode 100644
index 0000000..bcc3990
--- /dev/null
+++ b/spring-security/step-1/src/main/java/com/spring/security/SecurityWebConfiguration.java
@@ -0,0 +1,49 @@
+package com.spring.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+
+@EnableMethodSecurity
+@EnableWebSecurity
+@Configuration
+public class SecurityWebConfiguration {
+
+ @Bean
+ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ String[] permitAllUrls = {
+ "/", "/doc.html/**",
+ "/webjars/**", "/images/**", ".well-known/**", "favicon.ico", "/error/**",
+ "/v3/api-docs/**"
+ };
+
+ http.authorizeHttpRequests(authorizeRequests ->
+ // 访问路径为 /api/** 时需要进行认证
+ authorizeRequests
+ .requestMatchers("/api/**").authenticated()
+ .requestMatchers(permitAllUrls).permitAll()
+ )
+ .formLogin(loginPage -> loginPage
+ // 自定义登录页路径
+ .loginPage("/login-page")
+ // 处理登录的URL(默认就是/login)
+ .loginProcessingUrl("/login")
+ // 登录成功跳转
+ .defaultSuccessUrl("/")
+ // 登录失败跳转
+ .failureUrl("/login-page?error=true")
+ .permitAll()
+ )
+ // 使用默认的登录
+ // .formLogin(Customizer.withDefaults())
+ .logout(logout -> logout
+ .logoutSuccessUrl("/login-page?logout=true")
+ .permitAll()
+ );
+ return http.build();
+ }
+
+}
diff --git a/spring-security/step-1/src/main/java/com/spring/security/password/MD5PasswordEncoder.java b/spring-security/step-1/src/main/java/com/spring/security/password/MD5PasswordEncoder.java
new file mode 100644
index 0000000..d60e33a
--- /dev/null
+++ b/spring-security/step-1/src/main/java/com/spring/security/password/MD5PasswordEncoder.java
@@ -0,0 +1,53 @@
+package com.spring.security.password;
+
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.util.DigestUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.HexFormat;
+
+/**
+ * MD5密码编码器实现
+ *
+ * 安全警告:此类使用MD5算法进行密码哈希,已不再安全,不推荐用于生产环境。
+ *
+ * MD5算法因其计算速度快且易受彩虹表攻击而被认为不安全。即使密码哈希本身是单向的,
+ * 但现代计算能力使得暴力破解和预先计算的彩虹表攻击变得可行。
+ *
+ * Spring Security推荐使用BCrypt、PBKDF2、Argon2或Scrypt等自适应单向函数替代MD5。
+ *
+ * @see PasswordEncoder
+ * @deprecated 此类仅用于遗留系统兼容,新系统应使用更安全的密码编码器
+ */
+@Deprecated
+public class MD5PasswordEncoder implements PasswordEncoder {
+
+ @Override
+ public String encode(CharSequence rawPassword) {
+ if (rawPassword == null) {
+ throw new IllegalArgumentException("原始密码不能为null");
+ }
+
+ byte[] md5Digest = DigestUtils.md5Digest(rawPassword.toString().getBytes());
+ return HexFormat.of().formatHex(md5Digest);
+ }
+
+ @Override
+ public boolean matches(CharSequence rawPassword, String encodedPassword) {
+ if (rawPassword == null) {
+ throw new IllegalArgumentException("原始密码不能为null");
+ }
+
+ if (!StringUtils.hasText(encodedPassword)) {
+ return false;
+ }
+
+ return encodedPassword.equalsIgnoreCase(encode(rawPassword));
+ }
+
+ @Override
+ public boolean upgradeEncoding(String encodedPassword) {
+ // MD5已不安全,始终返回true建议升级到更安全的算法
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/spring-security/step-1/src/main/resources/application.yml b/spring-security/step-1/src/main/resources/application.yml
index 0bee250..8b65d6d 100644
--- a/spring-security/step-1/src/main/resources/application.yml
+++ b/spring-security/step-1/src/main/resources/application.yml
@@ -1,5 +1,5 @@
server:
- port: 8778
+ port: 8771
spring:
application:
diff --git a/spring-security/step-1/src/main/resources/static/favicon.ico b/spring-security/step-1/src/main/resources/static/favicon.ico
index 17f9dd1..385f8a6 100644
Binary files a/spring-security/step-1/src/main/resources/static/favicon.ico and b/spring-security/step-1/src/main/resources/static/favicon.ico differ
diff --git a/spring-security/step-1/src/main/resources/templates/login.html b/spring-security/step-1/src/main/resources/templates/login.html
new file mode 100644
index 0000000..f8b64b3
--- /dev/null
+++ b/spring-security/step-1/src/main/resources/templates/login.html
@@ -0,0 +1,206 @@
+
+
+
+
+
+ 登录 | 您的应用名称
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 无效的用户名或密码
+
+
+
+
+
+ 您已成功登出
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security/official/src/test/java/com/spring/SpringSecurityApplicationTests.java b/spring-security/step-1/src/test/java/com/spring/SpringSecurityStep1ApplicationTests.java
similarity index 80%
rename from spring-security/official/src/test/java/com/spring/SpringSecurityApplicationTests.java
rename to spring-security/step-1/src/test/java/com/spring/SpringSecurityStep1ApplicationTests.java
index 1463f61..9b2aa9c 100644
--- a/spring-security/official/src/test/java/com/spring/SpringSecurityApplicationTests.java
+++ b/spring-security/step-1/src/test/java/com/spring/SpringSecurityStep1ApplicationTests.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
-class SpringSecurityApplicationTests {
+class SpringSecurityStep1ApplicationTests {
@Test
void contextLoads() {