网站首页 > java教程 正文
源访问控制
概述
在构建Web应用时,我们经常需要实现诸如用户认证、资源访问控制等功能。Spring Boot 提供了多种工具来帮助开发者轻松实现这些需求。本文将介绍如何使用Spring Boot 3.x中的过滤器(Filter)和拦截器(Interceptor)来实现用户登录验证和对特定资源的访问控制。
技术栈
- Spring Boot 3.x
- Spring Security
- Spring Web
- Lombok
- Thymeleaf
业务需求
假设我们需要构建一个简单的博客平台,用户需要登录后才能发表评论或查看私人文章。为了实现这一需求,我们需要:
- 在用户尝试访问需要登录的功能时进行身份验证。
- 对特定资源(如私人文章)进行访问控制。
步骤详解
1. 配置Spring Security
首先,在WebSecurityConfig类中配置Spring Security来处理基本的身份验证和授权。
java
深色版本
1package com.example.blogapp.config;
2
3import org.springframework.context.annotation.Bean;
4import org.springframework.context.annotation.Configuration;
5import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
8import org.springframework.security.crypto.password.PasswordEncoder;
9import org.springframework.security.web.SecurityFilterChain;
10
11@Configuration
12@EnableWebSecurity
13public class WebSecurityConfig {
14
15 @Bean
16 public PasswordEncoder passwordEncoder() {
17 return new BCryptPasswordEncoder();
18 }
19
20 @Bean
21 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
22 http
23 .authorizeHttpRequests((authz) -> authz
24 .requestMatchers("/private/**").authenticated()
25 .anyRequest().permitAll()
26 )
27 .formLogin(form -> form
28 .loginPage("/login")
29 .permitAll()
30 )
31 .logout(logout -> logout
32 .permitAll()
33 );
34 return http.build();
35 }
36}
2. 实现过滤器
接下来,创建一个过滤器来处理登录请求前后的操作,例如记录登录日志。
java
深色版本
1package com.example.blogapp.filter;
2
3import javax.servlet.FilterChain;
4import javax.servlet.ServletException;
5import javax.servlet.ServletRequest;
6import javax.servlet.ServletResponse;
7import javax.servlet.http.HttpServletRequest;
8import javax.servlet.http.HttpServletResponse;
9import java.io.IOException;
10
11public class AuthFilter implements javax.servlet.Filter {
12
13 @Override
14 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
15 throws IOException, ServletException {
16 HttpServletRequest httpRequest = (HttpServletRequest) request;
17 HttpServletResponse httpResponse = (HttpServletResponse) response;
18
19 System.out.println("AuthFilter: Pre-processing for request to " + httpRequest.getRequestURI());
20
21 chain.doFilter(request, response);
22
23 System.out.println("AuthFilter: Post-processing for request to " + httpRequest.getRequestURI());
24 }
25}
在web.xml文件中配置过滤器:
xml
深色版本
1<filter>
2 <filter-name>authFilter</filter-name>
3 <filter-class>com.example.blogapp.filter.AuthFilter</filter-class>
4</filter>
5
6<filter-mapping>
7 <filter-name>authFilter</filter-name>
8 <url-pattern>/login</url-pattern>
9</filter-mapping>
3. 实现拦截器
然后,创建一个拦截器来控制对私人文章页面的访问。如果用户未登录,则重定向到登录页面。
java
深色版本
1package com.example.blogapp.interceptor;
2
3import org.springframework.stereotype.Component;
4import org.springframework.web.servlet.HandlerInterceptor;
5import org.springframework.web.servlet.ModelAndView;
6
7import javax.servlet.http.HttpServletRequest;
8import javax.servlet.http.HttpServletResponse;
9
10@Component
11public class AccessControlInterceptor implements HandlerInterceptor {
12
13 @Override
14 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
15 throws Exception {
16 if (request.getSession(false).getAttribute("user") == null) {
17 response.sendRedirect("/login");
18 return false;
19 }
20 return true;
21 }
22
23 @Override
24 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
25 ModelAndView modelAndView) throws Exception {
26 // 可以在这里添加一些额外的处理逻辑
27 }
28
29 @Override
30 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
31 throws Exception {
32 // 可以在这里添加一些清理逻辑
33 }
34}
在WebMvcConfigurer中注册拦截器:
java
深色版本
1package com.example.blogapp.config;
2
3import org.springframework.context.annotation.Configuration;
4import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
5import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
6
7@Configuration
8public class WebMvcConfig implements WebMvcConfigurer {
9
10 @Override
11 public void addInterceptors(InterceptorRegistry registry) {
12 registry.addInterceptor(new AccessControlInterceptor())
13 .addPathPatterns("/private/**")
14 .excludePathPatterns("/login");
15 }
16}
4. 创建控制器
接下来,定义两个控制器:一个用于处理登录流程,另一个用于展示私人文章。
java
深色版本
1package com.example.blogapp.controller;
2
3import org.springframework.security.core.Authentication;
4import org.springframework.security.core.context.SecurityContextHolder;
5import org.springframework.stereotype.Controller;
6import org.springframework.ui.Model;
7import org.springframework.web.bind.annotation.GetMapping;
8import org.springframework.web.bind.annotation.PostMapping;
9
10@Controller
11public class AuthController {
12
13 @GetMapping("/login")
14 public String showLoginPage() {
15 return "login";
16 }
17
18 @PostMapping("/login")
19 public String handleLogin() {
20 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
21 if (authentication != null && authentication.isAuthenticated()) {
22 return "redirect:/private/posts";
23 } else {
24 return "redirect:/login?error";
25 }
26 }
27}
java
深色版本
1package com.example.blogapp.controller;
2
3import org.springframework.security.core.Authentication;
4import org.springframework.security.core.context.SecurityContextHolder;
5import org.springframework.stereotype.Controller;
6import org.springframework.ui.Model;
7import org.springframework.web.bind.annotation.GetMapping;
8
9@Controller
10public class PostController {
11
12 @GetMapping("/private/posts")
13 public String showPrivatePosts(Model model) {
14 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
15 model.addAttribute("user", authentication.getName());
16 return "private-post";
17 }
18}
5. 页面模板
创建登录页面和私人文章页面的HTML模板。
html
深色版本
1<!-- src/main/resources/templates/login.html -->
2<!DOCTYPE html>
3<html xmlns:th="http://www.thymeleaf.org">
4<head>
5 <title>Login Page</title>
6</head>
7<body>
8 <h1>Login</h1>
9 <form th:action="@{/login}" method="post">
10 <label for="username">Username:</label>
11 <input type="text" id="username" name="username" required/>
12 <br/>
13 <label for="password">Password:</label>
14 <input type="password" id="password" name="password" required/>
15 <br/>
16 <input type="submit" value="Login"/>
17 </form>
18</body>
19</html>
html
深色版本
1<!-- src/main/resources/templates/private-post.html -->
2<!DOCTYPE html>
3<html xmlns:th="http://www.thymeleaf.org">
4<head>
5 <title>Private Posts</title>
6</head>
7<body>
8 <h1>Welcome, <span th:text="${user}"></span></h1>
9 <p>This is your private posts page.</p>
10</body>
11</html>
运行应用
启动应用后,尝试访问http://localhost:8080/private/posts,系统会自动重定向到登录页面。登录成功后,将可以看到私人文章页面。
结论
通过以上步骤,我们实现了基于Spring Boot的用户认证和资源访问控制。这种方式结合了Spring Security、过滤器和拦截器的强大功能,为我们的应用提供了安全性和灵活性。这种架构模式可以很容易地扩展到更复杂的业务场景中,例如多角色权限管理、审计日志记录等。
猜你喜欢
- 2024-11-04 【快学springboot】12.实现拦截器
- 2024-11-04 Spring Boot 中的拦截器和过滤器到底有什么区别?
- 2024-11-04 SpringBoot中的过滤器和拦截器有什么区别?
- 2024-11-04 为什么你写的拦截器注入不了Java bean?
- 2024-11-04 使用Spring Cloud Zuul实现过滤器或拦截器功能案例
- 2024-11-04 java服务-springboot拦截器实现用户登录Token及权限校验
- 2024-11-04 JAVAEE就业工程师教程之第4章 Struts2拦截器
- 2024-11-04 Spring框架功能分为哪些模块?(spring框架有哪几部分组成)
- 2024-11-04 高级码农Spring Boot实战进阶之过滤器、拦截器的使用
- 2024-11-04 轻量级 Java 权限认证框架Sa-Token初体验(五)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)