Spring Boot + Spring Security + Thymeleaf 举例

本文介绍如何使用SpringBoot结合SpringSecurity实现基本的权限管理功能,包括不同角色访问不同的页面,以及登录验证流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文以Spring Boot Thymeleaf为例,用Spring Security 保护 /admin 和 /user 页面

本例涉及的技术:

1. Spring Boot 1.5.6.REALEASE

2. Spring 4.3.8.REALEASE

3. Spring Security 4.2.2

4. Thymeleaf 2.2.5.REALEASE

5. Tomcat embed 8.5.14

6. Maven 3

7. Java 8

1. 项目目录结构


2. 项目依赖 pom.xml

<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>

  <groupId>org.thinkingingis</groupId>
  <artifactId>spring-boot-security</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-boot-security</name>
  <url>http://maven.apache.org</url>

  <parent>
  	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>
  
  <dependencies>
  	    <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>
         
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
  </dependencies>
  <build>
  	<plugins>
  		   	<!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
  	</plugins>
  </build>

</project>

3. Spring Security

3.1 继承自WebSecurityConfigurerAdapter 同时在configure方法中定义了安全角色

对于admin(管理员)角色来说:

a. 可以访问/admin.html页面

b. 不能访问/user.html页面,并重定向到403页面

对于user(用户)角色来说:

a.可以访问/user.html页面

b.不能访问/admin.html页面,并重定向到403页面

SpringSecurityConfig.java

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private AccessDeniedHandler accessDeniedHandler;
	
	protected void configure(HttpSecurity http) throws Exception{
		http.csrf().disable()
				.authorizeRequests()
					.antMatchers("/", "/home", "/about").permitAll()
					.antMatchers("/admin/**").hasAnyRole("ADMIN")
					.antMatchers("/user/**").hasAnyRole("USER")
					.anyRequest().authenticated()
				.and()
				.formLogin()
					.loginPage("/login")
					.permitAll()
					.and()
				.logout()
					.permitAll()
					.and()
				.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
	}
	
	//create two users admin and user
	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
		auth.inMemoryAuthentication()
				.withUser("user").password("password").roles("USER")
				.and()
				.withUser("admin").password("password").roles("ADMIN");
	}
	
}
3.2 定义403无权限访问的处理,重定向到/403页面

MyAccessDeniedHandler.java

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
	
	private static Logger logger = LoggerFactory.getLogger(MyAccessDeniedHandler.class);
	
	@Override
	public void handle( HttpServletRequest httpServletRequest, 
					    HttpServletResponse httpServletResponse, 
					    AccessDeniedException e)
			throws IOException, ServletException {
		
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		
		if(auth != null) {
			logger.info("User '" + auth.getName() + "' attempted to access the protected URL: " + httpServletRequest.getRequestURI());
		}
		
		httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");
	}

}

4. Spring Boot

4.1 DefaultController.java 

定义http请求和视图名

@Controller
public class DefaultController {
    
	@GetMapping("/")
    public String index() {
        return "/home";
    }

    @GetMapping("/home")
    public String home() {
        return "/home";
    }

    @GetMapping("/admin")
    public String admin() {
        return "/admin";
    }

    @GetMapping("/user")
    public String user() {
        return "/user";
    }

    @GetMapping("/about")
    public String about() {
        return "/about";
    }

    @GetMapping("/login")
    public String login() {
        return "/login";
    }

    @GetMapping("/403")
    public String error403() {
        return "/error/403";
    }
}

4.2 Spring Boot的启动程序

SpringBootWebApplication.java

@SpringBootApplication
public class SpringBootWebApplication {
	public static void main(String[] args) throws Exception {
		SpringApplication.run(SpringBootWebApplication.class, args);
	}

}

5.Thymeleaf及静态资源

对于 thymeleaf 文件,均放到 src/main/resources/templates/目录下

header.html

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:fragment="header-css">
        <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
        <link rel="stylesheet" th:href="@{/main.css}"/>
    </div>
</head>
<body>
<div th:fragment="header">
    <!-- this is header -->
    <nav class="navbar navbar-inverse">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" th:href="@{/}">ThinkingInGIS</a>
            </div>
            <div id="navbar" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a th:href="@{/}">Home</a></li>
                </ul>
            </div>
        </div>
    </nav>
</div>
footer.html

<html xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
</head>
<body>
<div th:fragment="footer">
    <div class="container">
        <footer>
        <!-- this is footer -->
        © 2017 ThinkingInGIS
            <span sec:authorize="isAuthenticated()">
                | Logged user: <span sec:authentication="name"></span> |
                Roles: <span sec:authentication="principal.authorities"></span> |
                <a th:href="@{/logout}">登出</a>
            </span>
        </footer>
    </div>
</div>
</body>
</html>
home.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Boot Thymeleaf + Spring Security</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <link rel="stylesheet" type="text/css" th:href="@{/main.css}"/>
   	<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
</head>
<body>
<div th:replace="fragments/header :: header"></div>
<div class="container">
    <div class="starter-template">
        <h1>Spring Boot + Thymeleaf + Spring Security 示例</h1>
        <h2>1. 打开 <a th:href="@{/admin}">管理员页面 (受 Spring Security 保护, 需要管理员权限)</a></h2>
        <h2>2. 打开 <a th:href="@{/user}">用户页面 (受 Spring Security 保护, 需要用户权限)</a></h2>
        <h2>3. 打开 <a th:href="@{/about}">游客页面</a></h2>
    </div>
</div>
<div th:replace="fragments/footer :: footer"></div>
</body>
</html>

admin.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>

<div class="container">
    <div class="starter-template">
        <h1>GORGEOUS! 管理员页面 (受 Spring Security 保护, 需要管理员权限)</h1>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" class="btn btn-danger" value="登出"/>
        </form>
    </div>
</div>
<div class="container">
    <footer>
        <p>
            © <a >ThinkingInGIS</a> 2017
        </p>
    </footer>
</div>
</body>
</html>
user.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>

<div class="container">
    <div class="starter-template">
        <h1>普通用户页面 (受 Spring Security 保护, 需要用户权限)</h1>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" class="btn btn-danger" value="登出"/>
        </form>
    </div>
</div>
<div class="container">
    <footer>
        <p>
            © <a >ThinkingInGIS</a> 2017
        </p>
    </footer>
</div>
</body>
</html>
about.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>

<div class="container">
    <div class="starter-template">
        <h1>游客页面 无需登录</h1>
    </div>
</div>
<div class="container">
    <footer>
        <p>
            © <a >ThinkingInGIS</a> 2017
        </p>
    </footer>
</div>
</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<div th:replace="fragments/header :: header"></div>
<div class="container">
    <div class="row" style="margin-top:20px">
        <div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
            <form th:action="@{/login}" method="post">
                <fieldset>
                    <h1>登录</h1>
                    <div th:if="${param.error}">
                        <div class="alert alert-danger">
                            Invalid username and password.
                        </div>
                    </div>
                    <div th:if="${param.logout}">
                        <div class="alert alert-info">
                            You have been logged out.
                        </div>
                    </div>

                    <div class="form-group">
                        <input type="text" name="username" id="username" class="form-control input-lg"
                               placeholder="用户名" required="true" autofocus="true"/>
                    </div>
                    <div class="form-group">
                        <input type="password" name="password" id="password" class="form-control input-lg"
                               placeholder="密码" required="true"/>
                    </div>

                    <div class="row">
                        <div class="col-xs-6 col-sm-6 col-md-6">
                            <input type="submit" class="btn btn-lg btn-primary btn-block" value="登录"/>
                        </div>
                        <div class="col-xs-6 col-sm-6 col-md-6">
                        </div>
                    </div>
                </fieldset>
            </form>
        </div>
    </div>

</div>

<div th:replace="fragments/footer :: footer"></div>

</body>
</html>
403.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>403</title>
    <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<div th:replace="fragments/header :: header"></div>
<div class="container">
    <div class="starter-template">
        <h1>403 - 没有访问权限</h1>
        <div th:inline="text">Hello '[[${#httpServletRequest.remoteUser}]]',
                你没有权限访问此页面.</div>
    </div>
</div>
<!-- /.container -->
<div th:replace="fragments/footer :: footer"></div>

</body>
</html>
6.启动程序

6.1 /admin 下面的需要用admin用户登录才能访问

6.2 启动程序,访问 http://localhost:8080/

6.3 访问http://localhost:8080/admin 会被重定向到 http://localhost:8080/login


6.4 当输入无效的用户名和密码后...


6.5 用户名输入admin  密码输入 password 登录,页面会进入到 http://localhost:8080/admin


6.6 输入http://localhost:8080/user 会被重定向到 http://localhost:8080/403 最下面显示了登录的角色及用户名


6.7 点击 登出 会重定向到http://localhost:8080/login?logout


最后,自己试试 用 'user' 访问admin页面可看会有上面结果吧。

源码地址:https://github.com/ThinkingInGIS/spring-boot-security.git

至此,一个简单的spring boot + thymeleaf + spring security 程序 就搭建好了。
(如遇到问题,请留言给作者,以便共同探讨gis知识。thinkingingis@qq.com)
更多干货 欢迎关注微信公众号: ThinkingInGIS


如果觉得本文对你有帮助,是可以赞赏作者的哦


<think>好的,用户让我比较Django和Spring Boot。之前他问过Virtualenv,现在转向这两个框架,可能他正在学习后端开发,想选一个合适的框架。我需要先分析两者的背景、特点、适用场景,然后给出对比。 首先,Django是Python的框架,而Spring BootJava的。用户可能对这两种语言不太熟悉,或者想了解哪个更适合自己的项目。需要比较它们的语言特性,比如Python的简洁和Java的性能。 接下来,框架的设计哲学。Django是“开箱即用”,内置了很多功能,比如ORM、Admin界面,适合快速开发。Spring Boot则是约定优于配置,简化了Spring的配置,依赖注入和模块化更强。用户可能关心开发效率和灵活性之间的权衡。 性能方面,Java通常比Python快,特别是在高并发场景,比如微服务。但Django可能更适合内容管理或快速原型开发。需要提到两者的性能差异和使用场景。 生态系统和社区支持。Spring BootSpring生态,整合各种工具和库,适合企业级应用。Django的社区活跃,插件丰富,适合中小型项目。用户可能在考虑长期维护和扩展性。 学习曲线方面,Python容易上手,适合新手;Java需要更深入的学习,尤其是Spring的复杂性。用户如果是初学者,可能会倾向于Django,但如果有Java背景,Spring Boot更合适。 实际应用场景举例,比如Django适合CMS、社交网站,Spring Boot适合电商、金融系统。用户可能有特定的项目类型,需要明确哪个框架更适合。 最后,是否需要给出建议?如果用户的项目需要快速开发、简单,选Django;如果需要高性能、大型系统,选Spring Boot。还要考虑团队熟悉度和资源。 要确保回答结构清晰,对比点明确,让用户能根据自身情况做出选择。避免使用太多技术术语,保持易懂。同时检查是否有遗漏的重要对比点,比如安全性、数据库支持、REST API开发等。</think>好的!**Django**(Python 框架)和 **Spring Boot**(Java 框架)是两种流行的后端开发框架,各有其设计理念和适用场景。以下是它们的核心对比: --- ### **1. 语言与生态** | **特性** | **Django** | **Spring Boot** | |----------------|---------------------------------|--------------------------------| | **语言** | Python(动态类型,语法简洁) | Java/Kotlin(静态类型,性能高)| | **生态系统** | Python 生态(AI/数据分析友好) | Java 生态(企业级工具链完善) | | **设计哲学** | “开箱即用” (全功能内置) | “约定优于配置” (高度模块化) | --- ### **2. 核心功能对比** | **功能** | **Django** | **Spring Boot** | |------------------|-------------------------------------------------|----------------------------------------------| | **ORM** | 内置 Django ORM,简单易用 | 整合 Hibernate/JPA,灵活但配置复杂 | | **路由与视图** | 通过 `urls.py` 和视图函数定义 | 通过注解(`@RestController`)或配置文件定义 | | **模板引擎** | 内置 Django Template | 支持 Thymeleaf、Freemarker 等 | | **安全机制** | 内置 CSRF、XSS 防护,用户认证系统 | 依赖 Spring Security(功能强大,学习成本高) | | **Admin 后台** | 自带 Admin 面板(快速生成数据管理界面) | 需自行开发或整合第三方库(如 Spring Data REST) | --- ### **3. 开发效率与性能** | **维度** | **Django** | **Spring Boot** | |----------------|-------------------------------------------------|----------------------------------------------| | **开发速度** | 更**快**(自动化工具多,适合快速原型开发) | 较慢(需更多配置,适合复杂业务逻辑) | | **性能** | 一般(Python 解释器性能瓶颈) | 更高(JVM 优化,适合高并发场景) | | **微服务支持** | 需依赖第三方库(如 Django REST Framework) | 原生支持(Spring Cloud 生态完善) | --- ### **4. 适用场景** | **场景** | **Django** | **Spring Boot** | |------------------------|-------------------------------------------------|----------------------------------------------| | **推荐用途** | - 内容管理(CMS)<br>- 快速原型开发<br>- 中小型 Web 应用 | - 企业级应用(如电商、金融系统)<br>- 微服务架构<br>- 高并发后端服务 | | **典型案例** | Instagram、Pinterest | Netflix、阿里巴巴 | | **适合团队** | 初创团队、Python 开发者、全栈工程师 | 中大型企业团队、Java 开发者 | --- ### **5. 学习曲线与工具链** | **维度** | **Django** | **Spring Boot** | |----------------|-------------------------------------------------|----------------------------------------------| | **学习门槛** | 较低(Python 语法简单,文档清晰) | 较高(需熟悉 Java 生态、Spring 体系) | | **调试工具** | 内置开发服务器、Debug 页面 | 依赖 IDE(如 IntelliJ IDEA)、Spring DevTools| | **依赖管理** | `requirements.txt` | Maven/Gradle | --- ### **6. 扩展性与维护** | **维度** | **Django** | **Spring Boot** | |----------------|-------------------------------------------------|----------------------------------------------| | **扩展性** | 适合中小型项目,大型项目需优化架构 | 更适合复杂、高扩展性系统 | | **维护成本** | 较低(代码量少,逻辑直观) | 较高(配置复杂,需管理 Java 依赖) | | **社区支持** | 活跃的 Python 社区 | 强大的企业级支持(Spring 生态成熟) | --- ### **总结:如何选择?** - **选 Django 如果**: - 快速开发、轻量级项目为主 - 团队熟悉 Python 或需要结合 AI/数据分析 - 需要内置功能(如 Admin、ORM)减少重复工作 - **选 Spring Boot 如果**: - 项目复杂度高、需要高性能和扩展性 - 企业级开发(如分布式系统、微服务) - 团队有 Java 基础或需长期维护的大型系统 --- ### **示例代码对比** #### Django(Python)的简单 API: ```python # views.py from django.http import JsonResponse def hello(request): return JsonResponse({"message": "Hello Django!"}) # urls.py from django.urls import path from . import views urlpatterns = [ path('hello/', views.hello), ] ``` #### Spring BootJava)的简单 API: ```java // HelloController.java @RestController public class HelloController { @GetMapping("/hello") public Map<String, String> hello() { return Map.of("message", "Hello Spring Boot!"); } } ``` --- 两者无绝对优劣,关键在于**项目需求**和**团队技术栈**。如果是个人学习
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值