Code Ease Code Ease
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档

神秘的鱼仔

你会累是因为你在走上坡路
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档
服务器
  • Java核心基础

  • 框架的艺术

    • Spring

    • Mybatis

    • SpringBoot

      • 如何用SpringBoot(2.3.3版本)快速搭建一个项目
      • 一步步带你看SpringBoot(2.3.3版本)自动装配原理
      • SpringBoot配置文件及自动配置原理详解,这应该是SpringBoot最大的优势了吧
      • SpringBoot整合jdbc、durid、mybatis详解,数据库的连接就是这么简单
      • SpringBoot整合SpringSecurity详解,认证授权从未如此简单
        • (一)概述
        • (二)前期项目搭建
        • (三)认证与授权
        • (四)注销的操作
        • (五)记住密码功能
      • SpringBoot整合Shiro详解,还在自己写登陆注册早落伍了
      • SpringBoot如何实现异步、定时任务?
      • 如何在SpringBoot启动时执行初始化操作,两个简单接口就可以实现
      • 如何使用SpringBoot写一个属于自己的Starter
      • SpringBoot请求日志,如何优雅地打印
      • 主线程的用户信息,到子线程怎么丢了
    • MQ

    • Zookeeper

    • netty

  • 分布式与微服务

  • 开发经验大全

  • 版本新特性

  • Java
  • 框架的艺术
  • SpringBoot
CodeEase
2023-09-28
目录

SpringBoot整合SpringSecurity详解,认证授权从未如此简单

作者:鱼仔
博客首页: codeease.top (opens new window)
公众号:Java鱼仔

# (一)概述

对于一个Web项目来说,最重要的不是功能酷不酷炫,而是这个项目安不安全。做过项目的人都知道,一个项目在上线前一定会经过安全漏扫,只有通过安全漏扫后这个项目才能正式上线。 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,类似的安全框架还有Shiro。 Spring Security主要做两个事情,认证、授权。

# (二)前期项目搭建

为了更好的展示SpringSecurity,我们先搭建一个简单的web项目出来。引入thymeleaf依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12

新建一个登陆页,一个首页,然后几个不同等级的展示页面: login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆页</title>
</head>
<body>
<div>
    <form>
        <h2>登陆页</h2>
        <input type="text" id="username" placeholder="username">
        <input type="password" id="password" placeholder="password">
        <button type="button">登陆</button>
    </form>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

首页index.html,主要就展示不同等级的按钮,为之后授权做准备

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<div>
    <h2>首页</h2>
    <a href="/login">登陆</a>
    <div style="overflow: hidden">
        <div style="float: left;margin-left: 20px">
            <h3>level1</h3>
            <a href="/level1/1">level-1-1</a>
            <hr>
            <a href="/level1/2">level-1-2</a>
        </div>
        <div style="float: left;margin-left: 20px">
            <h3>level2</h3>
            <a href="/level2/1">level-2-1</a>
            <hr>
            <a href="/level2/2">level-2-2</a>
        </div>
        <div style="float: left;margin-left: 20px">
            <h3>level3</h3>
            <a href="/level3/1">level-3-1</a>
            <hr>
            <a href="/level3/2">level-3-2</a>
        </div>
    </div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

另外还有几个不同等级的页面

5-1.png

分别在body中写上自己对应的编号。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
level-1-1
</body>
</html>
1
2
3
4
5
6
7
8
9
10

最后编写一个controller来接收请求:

@Controller
public class RouteController {
    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }
    @RequestMapping("/login")
    public String toLogin(){
        return "login";
    }
    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id")String id){
        return "level1/"+id;
    }
    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id")String id){
        return "level2/"+id;
    }
    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id")String id){
        return "level3/"+id;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

最终的效果如下:

5-2.png

首页效果如下:

5-3.png

# (三)认证与授权

在上面的这个页面中有两个问题,第一未做登陆认证的处理,第二三个level页面现在都能被所有人访问,未做授权。而上面的这两个问题都可以通过SpringSecurity来解决。

实现SpringSecurity只需要引入spring-boot-starter-security依赖,进行少量的配置,就可以实现强大的安全管理功能。

在正式接触前我们需要记住几个类: 1.WebSecurityConfigurerAdapter :自定义Security策略 2.AuthenticationManagerBuilder:自定义认证策略 3.@EnableWebSecurity :开启WebSecurity模式

我们新建一个config包,创建一个配置类SecurityConfig,继承WebSecurityConfigurerAdapter接口

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人都能访问,level页面只有有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限默认跳到登陆页,默认会重定向到/login
        http.formLogin();
    }
    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                .and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

通过上面的这段代码,实现了授权和认证的功能,其中认证方法在内存中存入的用户信息。正常情况下用户的数据是从数据库中获取,授权功能给不同的页面设置不同的角色。

我们再次打开首页http://localhost:8080/,所有人都有权限看到,当我们点击里面的level1 2 3里的链接时,自动跳转到了http://localhost:8080/login

5-4.png

你会发现这个登陆页面明明不是自己写的,怎么就出现了?其实这就是SpringSecurity所提供的,http.formLogin();这段代码做了对登陆页的处理,没有权限默认跳到登陆页,默认会重定向到/login。

当我们用不同权限的账号登陆时,就能点击不同权限的链接,如果点击权限外的链接时,会报403错误

5-5.png

# (四)注销的操作

既然有认证和授权,那么一定免不了注销的功能,SpringSecurity实现注销很简单,你只需要在SecurityConfig类的授权代码里增加一条代码。

//登出
http.logout();
1
2

然后在前端index.html代码中增加一个注销的标签

<a href="/logout">注销</a>
1

点击首页的注销按钮后就会跳转到SpringSecurity的注销提示界面

5-6.png

点击logout按钮后自动退出到登陆页面,如果你希望注销后还是回到首页的话,可以将注销代码修改成下面的方式:

http.logout().logoutSuccessUrl("/");
1

# (五)记住密码功能

一般情况下登陆页面肯定会有一个记住密码的功能,这个功能其实就是在本地生成一个cookie,用原生的java实现虽然不难,但是也需要一定的代码。而使用SpringSecurity只需要一行:

http.rememberMe();
1

再次进入登陆页面后,就可以看到增加了一行记住密码的选项

5-7.png

上次更新: 2025/04/29, 17:22:06
SpringBoot整合jdbc、durid、mybatis详解,数据库的连接就是这么简单
SpringBoot整合Shiro详解,还在自己写登陆注册早落伍了

← SpringBoot整合jdbc、durid、mybatis详解,数据库的连接就是这么简单 SpringBoot整合Shiro详解,还在自己写登陆注册早落伍了→

最近更新
01
AI大模型部署指南
02-18
02
半个月了,DeepSeek为什么还是服务不可用
02-13
03
Python3.9及3.10安装文档
01-23
更多文章>
Theme by Vdoing | Copyright © 2023-2025 备案图标 浙公网安备33021202002405 | 浙ICP备2023040452号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式