【SpringBoot】(四)SpringBoot + SpringSecurity + Thymeleaf 整合

  • Post author:
  • Post category:其他


在 SpringBoot 工程中,借用 SpringSecurity 权限框架来对登录用户所拥有的不同的权限来显示不同的页面。并且,如果有用户已登录,则右上角显示用户名和其角色。如下图:

admin 用户权限最大,显示所有页面内容:

在这里插入图片描述

zzc 用户只有两个角色权限,所以,只显示部分内容:

在这里插入图片描述

没有用户登录时,页面显示如下:

在这里插入图片描述

【首页】、【登录】下方的内容都没有显示。

好了,需求已经了解清楚了,那咱们就直接上代码了哈。【文末有源码】



【开发环境】:

  • IDEA-2020.2
  • SpringBoot-2.5.5
  • MAVEN-3.5.3
  • SpringSecurity
  • Thymeleaf


项目结构图

后台:

在这里插入图片描述

前台:

在这里插入图片描述


1、引入依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springsecurity -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- thymeleaf -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- thymeleaf-springsecurity -->
<dependency>
  <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>


2、添加

application.yml

配置:

spring:
  thymeleaf:
    cache: false
    prefix: classpath:/templates/  # 配置模板(非必要) 默认是 templates
    suffix: .html


3、后台路由控制器

RoutingController

@Controller
public class RoutingController {

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

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

    @GetMapping("/level1/{id}")
    public String level1(@PathVariable("id") int id) {
        return "views/level1/" + id;
    }

    @GetMapping("/level2/{id}")
    public String level2(@PathVariable("id") int id) {
        return "views/level2/" + id;
    }

    @GetMapping("/level3/{id}")
    public String level3(@PathVariable("id") int id) {
        return "views/level3/" + id;
    }

}


4、SpringSecurity 配置类

SecurityConfig

使用 SpringSecurity 需要添加一个配置类:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 1.配置请求授权规则
        // 首页所有人可以访问;其它页面需要相应的角色权限才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");

        // 2.没有权限,默认会跳转到登录页面,需要开启登录页面
        http.formLogin()
        // 自定义登录页面
        .loginPage("/toLogin").usernameParameter("name").passwordParameter("pwd").loginProcessingUrl("/login");
        // 关闭csrf
        http.csrf().disable();
        // 3.注销,跳转到首页
        http.logout().logoutSuccessUrl("/");
    }

    // 认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // inMemoryAuthentication:从内存中认证;jdbcAuthentication:从数据库中认证
        // BCryptPasswordEncoder:密码编码规则,如果没有设置,则登录时会报错
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("zzc").password(new BCryptPasswordEncoder().encode("66666")).roles("vip1", "vip3")
                .and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("vip1", "vip2", "vip3");
    }

}
  • configure(HttpSecurity http):配置了访问哪些 url,需要相对应的角色
  • configure(AuthenticationManagerBuilder auth):配置了哪些用户有哪些角色


5、前台首页

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <link rel="stylesheet" th:href="@{/css/index.css}" />
</head>
<body>
<div id="container">
    <div id="nav" class="clearfloat">
        <div class="nav" id="first_page"><a th:href="@{/index}">首页</a></div>
        <div class="nav" id="logout" sec:authorize="isAuthenticated()">
            <div>
                用户名:<span sec:authentication="name"></span>
                角色:<span sec:authentication="principal.authorities"></span>
            </div>
            <a th:href="@{/logout}">注销</a>
        </div>
        <div class="nav" id="login" sec:authorize="!isAuthenticated()">
            <a th:href="@{/toLogin}">登录</a>
        </div>
    </div>
    <div id="middle"></div>
    <div id="bottom">
        <div class="box" sec:authorize="hasRole('vip1')">
            <div>Level1</div>
            <a href="/level1/1">level1-1</a>
            <a href="/level1/2">level1-2</a>
            <a href="/level1/3">level1-3</a>
        </div>
        <div class="box" sec:authorize="hasRole('vip2')">
            <div>Level2</div>
            <a href="/level2/1">level2-1</a>
            <a href="/level2/2">level2-2</a>
            <a href="/level2/3">level2-3</a>
        </div>
        <div class="box" sec:authorize="hasRole('vip3')">
            <div>Level3</div>
            <a href="/level3/1">level3-1</a>
            <a href="/level3/2">level3-2</a>
            <a href="/level3/3">level3-3</a>
        </div>
    </div>
</div>
</body>
</html>

这段代码:

<div class="nav" id="logout" sec:authorize="isAuthenticated()">
    <div>
        用户名:<span sec:authentication="name"></span>
        角色:<span sec:authentication="principal.authorities"></span>
    </div>
    <a th:href="@{/logout}">注销</a>
</div>

当用户登录后,就显示用户名和角色

这段代码:

<div class="box" sec:authorize="hasRole('vip1')">
    <div>Level1</div>
    <a href="/level1/1">level1-1</a>
    <a href="/level1/2">level1-2</a>
    <a href="/level1/3">level1-3</a>
</div>

只有角色是

vip1

的时候,才显示其内容


6、登录页面

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<form method="post" th:action="@{/login}">
    用户名:<input type="text" name="name" /><br>
    密码:<input type="password" name="pwd" /><br>
    <input type="submit" value="登录" />
</form>
</body>
</html>


【注意】:这里的登录后台接口是

/login

,但是,在我们自己的后台接口中是没有这个接口的,它是通过 SpringSecurity 进行处理的。

所以,我们

SecurityConfig#configure(HttpSecurity http)

方法中有如下代码:

 http.formLogin()
        // 自定义登录页面
   	.loginPage("/toLogin").usernameParameter("name").passwordParameter("pwd").loginProcessingUrl("/login");


7、页面内容

1.html

level1/level2/level3 文件夹下的 html 文件内容基本一致,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>level1-1</h1>
</body>
</html>

这里就不重复粘贴了哈。


源代码已上传至码云



版权声明:本文为sco5282原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。