- 项目结构
src
└── main
├── java
│ └── com.example.securitydemo
│ ├── RestapiApplication.java
│ ├── config
│ │ └── SecurityConfig.java
│ ├── controller
│ │ └── UserController.java
│ └── service
│ └── CustomUserDetailsService.java
└── resources
├── templates
│ ├── login.html
│ ├── home.html
│ ├── admin.html
├── static
│ └── css
│ └── styles.css
└── application.properties - 创建主应用类
package cn.mayanan.restapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RestapiApplication {
public static void main(String[] args) {
SpringApplication.run(RestapiApplication.class, args);
}
}
- 配置 Spring Security, 创建用户服务
package cn.mayanan.restapi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.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;
// 标注配置类,表示该类包含了spring配置
@Configuration
public class SecurityConfig {
// 在配置类中标注,用于定义具体的Bean
@Bean
public PasswordEncoder passwordEncoder() {
// 使用BCrypt作为密码编码器
return new BCryptPasswordEncoder();
}
// 自定义认证管理器
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 禁用csrf,仅限开发时使用
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/public/**", "/css/**").permitAll() // 公开的资源
.requestMatchers("/admin").hasRole("ADMIN") // 仅ADMIN角色可以访问
.requestMatchers("/api/users").hasAnyRole("USER", "ADMIN") // USER和ADMIN角色可以访问
.anyRequest().authenticated() // 其他请求需要认证
)
.formLogin(form -> form
.loginPage("/login") // 自定义登录页面
.defaultSuccessUrl("/home", true) // 登录成功后跳转的页面
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout") // 登出的url
.logoutSuccessUrl("/login") // 登出成功后跳转的页面
.permitAll()
);
return http.build();
}
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("123"))
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder.encode("456"))
.roles("ADMIN")
.build();
UserDetails superuser = User.builder()
.username("superuser")
.password(passwordEncoder.encode("789"))
.roles("SUPERUSER")
.build();
return new InMemoryUserDetailsManager(user, admin, superuser);
}
}
- 创建控制器
package cn.mayanan.restapi.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@GetMapping("/home")
public String home() {
return "home";
}
@GetMapping("/admin")
public String admin() {
return "admin";
}
@GetMapping("/login")
public String loginPage() {
return "login";
}
}
- 添加 HTML 页面
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Login</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h2>Login</h2>
<form method="post" action="/login">
<label for="username">Username:</label>
<input type="text" name="username" required><br>
<label for="password">Password:</label>
<input type="password" name="password" required><br>
<button type="submit">Login</button>
</form>
<p>Don't have an account? Contact admin!</p>
</body>
</html>
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome Home!</h1>
<p>You are logged in.</p>
<a href="/logout">Logout</a>
</body>
</html>
admin.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Admin Page</title>
</head>
<body>
<h1>Welcome, Admin!</h1>
<p>Only admins can see this page.</p>
<a href="/logout">Logout</a>
</body>
</html>
- 添加静态资源(CSS)
在 src/main/resources/static/css/styles.css 中:
body {
font-family: Arial, sans-serif;
margin: 20px;
}
form {
margin: 20px 0;
}
label {
display: block;
margin-bottom: 5px;
}
input {
margin-bottom: 10px;
}
- 配置 application.yml
spring.thymeleaf.cache=false
运行步骤
启动项目。
访问 http://localhost:8080/login 进入登录页面。
用户名:user,密码:password
用户名:admin,密码:admin
登录后:
http://localhost:8080/home:普通用户和管理员都可访问。
http://localhost:8080/admin:仅管理员可访问。
登出:点击页面中的 Logout