SpringBoot SpringSecurity JWT实现系统安全策略详解

SpringBoot SpringSecurity JWT实现系统安全策略详解

1. 什么是JWT

JWT(JSON Web Token)是一种用于认证的开放标准。可以基于HTTP协议上的Bearer认证方式对用户进行身份验证和授权。JWT由三部分组成:头部、载荷以及签名。

头部:包含了加密算法、哪种类型的token(例如,Bearer),可以使用什么类型的算法来进行加密等信息。

载荷:是存放有效信息的地方,可以自定义信息字段,例如用户id、登陆时间、有效期等。

签名:是第三段,主要用来验证上面两部分的合法性,保证信息不会被篡改。

2. 为何选择SpringBoot SpringSecurity JWT

SpringBoot是一个非常流行的Java Web开发框架,通过SpringBoot开发一个Web应用非常容易、便捷、高效。

而SpringSecurity是Spring提供的一个安全框架,它实现了许多常用的安全功能,如权限设置、身份认证等,使用SpringSecurity能为应用程序提供安全支持,保证应用程序的安全性。

使用JWT认证,能够实现无状态的验证,不需要在服务器端保存Session,有效攻击防御XSS、CSRF、SQL Injection等常见的攻击。

3. JWT实现系统安全策略步骤

  1. 引入SpringBoot、SpringSecurity和JWT依赖

在使用SpringBoot开发一个应用程序时,可以添加对应的依赖来简化操作。首先在pom.xml 中添加以下依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
  1. 对JWT进行配置

首先要定义一个类,用于封装加密JWT时需要的信息,包括JWT的发行人、主题等。如下:

@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtConfig {

    // key
    private String key;

    // 过期时间,单位:秒。默认2小时
    private long expire = 7200;

    // header字段
    private String header = "Authorization";

    // token 前缀
    private String prefix = "Bearer ";

    // 获取 JWT 签发者
    private String issuer;

    // 获取指定的声明
    private Map<String, Object> claims = new HashMap<>();
    // getter setter 设置默认值
}

主要考虑到了:

  • key 就是 JWT 的密钥
  • expire 是 JWT 的有效期,单位是 秒
  • header 是将 JWT 存储在 HTTP 请求中时的 key
  • prefix 是 JWT 存储时,前缀字符串
  • issuer 表示 JWT 签发者
  • claims 表示 JWT 自身声明信息

  • 在 Spring Security 配置类中添加 JWT

首先编写一个获取用户ID的方法public String getCurrentUserId() { ... },根据当前的 Authentication 对象获取当前用户 ID。

编写完毕后,我们就可以在 Spring Security 配置类中使用JWT了。如下:

@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtConfig jwtConfig;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new AuthenticationTokenFilter(jwtConfig, jwtUserDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        // 允许访问的接口
        http.authorizeRequests()
                .antMatchers(
                        "/swagger-ui.html",
                        "/swagger-resources/**",
                        "/v2/api-docs",
                        "/auth/**"
                )
                .permitAll();

        http.authorizeRequests().anyRequest().authenticated();

        // 定义登录页和默认跳转路径
        http.formLogin().loginPage("/auth/login").defaultSuccessURL("/").permitAll();

        // 定义登出操作
        http.logout().logoutUrl("/auth/logout").permitAll()
                .logoutSuccessUrl("/auth/login");

        // 添加JWT过滤器
        http.addFilterBefore(authenticationTokenFilterBean(),
                UsernamePasswordAuthenticationFilter.class);
    }
}
  1. 使用JWT进行用户认证

在登录接口中,用户需要提供用户名和密码,系统通过加密之后获得JWT的Token,然后返回给客户端。客户端访问服务器的其他接口时,将Token作为Authorization字段加入HTTP请求头中传递给服务器。

如果JWT验证成功,则说明用户已经登陆了,可以访问需要登陆才能访问的API了。例如:

@RestController
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/hello")
    @PreAuthorize("hasRole('USER')")
    public String hello() {
        return "Hello, JWT!";
    }
}

4. 示例说明

示例1:通过JWT认证需要用户登录后才能获取的资料

  1. 登录
POST:/auth/login
BODY:
{
    "username": "test",
    "password": "123456"
}

返回:

{
    "code": 200,
    "msg": "登录成功",
    "data": {
        "id": 1,
        "username" : "test",
        "token": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTkyNTc0MzEyLCJleHAiOjE1OTI1OTExMTIsImF1ZCI6InBhc3N3b3JkIiwiaXNzIjoibmlnaHQiLCJuYmYiOjE1OTI1NzQzMTJ9.aFT_iSOLOZFTZiS5iOONCTwb5tU5-2bzcE1k8H5jvXw"
    }
}

  1. 获取需要认证才能访问的资源
GET:/api/hello
Header:
   Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTkyNTc0MzEyLCJleHAiOjE1OTI1OTEwOTIsImF1ZCI6InBhc3N3b3JkIiwiaXNzIjoibmlnaHQiLCJuYmYiOjE1OTI1NzQzMTJ9.aFT_iSOLOZFTZiS5iOONCTwb5tU5-2bzcE1k8H5jvXw

返回:

{
    "code": 200,
    "msg": "请求成功",
    "data": "Hello, JWT!"
}

示例2:使用JWT实现文件上传接口的安全

  1. 登录
POST:/auth/login
BODY:
{
    "username": "test",
    "password": "123456"
}

返回:

{
    "code": 200,
    "msg": "登录成功",
    "data": {
        "id": 1,
        "username": "test",
        "token": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTkyNTc0MzEyLCJleHAiOjE1OTI1OTEwOTIsImF1ZCI6InBhc3N3b3JkIiwiaXNzIjoibmlnaHQiLCJuYmYiOjE1OTI1NzQzMTJ9.aFT_iSOLOZFTZiS5iOONCTwb5tU5-2bzcE1k8H5jvXw"
    }
}

  1. 上传文件
POST:/api/file/upload
Header:
   Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTkyNTc0MzEyLCJleHAiOjE1OTI1OTEwOTIsImF1ZCI6InBhc3N3b3JkIiwiaXNzIjoibmlnaHQiLCJuYmYiOjE1OTI1NzQzMTJ9.aFT_iSOLOZFTZiS5iOONCTwb5tU5-2bzcE1k8H5jvXw

BODY:
{
    "file": "Base64文件字符串"
}

返回:

{
    "code": 200,
    "msg": "请求成功",
    "data": "文件上传成功"
}

以上就是使用SpringBoot、SpringSecurity和JWT实现系统安全策略的详细攻略,具体实现方法可以参考示例。

阅读剩余 81%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot SpringSecurity JWT实现系统安全策略详解 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • AngularJS入门教程之 XMLHttpRequest实例讲解

    AngularJS入门教程之 XMLHttpRequest实例讲解 介绍 在使用 AngularJS 进行 Web 开发的过程中,我们通常会需要使用 http 请求来获取数据或者提交数据。而 XMLHttpRequest,则是实现这一功能时必不可少的 API 之一。本文主要介绍如何在 AngularJS 中使用 XMLHttpRequest 进行 http …

    Java 2023年6月15日
    00
  • Eclipse最新版使用过程中遇到的问题总结

    Eclipse最新版使用过程中遇到的问题总结 作为一款强大的Java开发工具,Eclipse在开发中的使用率非常高。然而,在使用过程中可能会遇到一些问题,需要进行解决。本文总结了Eclipse最新版使用过程中可能遇到的问题及其解决方法,方便开发者在使用过程中进行参考。 问题一:Eclipse启动缓慢 在启动Eclipse时,会花费较长时间进行加载,影响开发效…

    Java 2023年5月19日
    00
  • JVM相关面试题及答案(小结)

    下面是针对“JVM相关面试题及答案(小结)”这篇文章的详细讲解攻略: 1. 简介 该文章主要介绍了与JVM有关的面试题目及答案,共分为3个部分:JVM基础知识、JVM垃圾回收以及JVM调优。该文章的目的是为了帮助读者提高对JVM的了解,并在面试过程中做好准备。 2. JVM基础知识 该部分主要介绍了JVM的一些基础知识,包括JVM的体系结构、类加载器以及线程…

    Java 2023年5月19日
    00
  • 基于JS实现导航条flash导航条

    针对“基于JS实现导航条flash导航条”的完整攻略,我给出如下详细讲解: 介绍 flash导航条,是通过flash技术来实现网站导航栏,使导航效果更为优美且富有动感。在近年来,随着web前端技术的发展,人们开始尝试使用javascript的方式实现类似的效果。下面参加我将通过两个案例,详细解释如何通过JS实现这样一个效果。 实现思路 实现flash导航条,…

    Java 2023年6月15日
    00
  • 一篇文章读懂Java哈希与一致性哈希算法

    一篇文章读懂Java哈希与一致性哈希算法 1. 哈希算法基础 在计算机科学中,哈希算法是将任意长度的消息映射到固定长度的摘要 (或称哈希值) 的函数,也就是根据某种规则,将任意数据映射到指定大小范围的数值上,一般用于唯一性标识、数据校验等场景。 Java提供了多种哈希算法,比如MD5、SHA1、SHA256等,这些哈希算法的实现已经被封装在Java的类库中的…

    Java 2023年5月19日
    00
  • Java毕业设计实战之食品溯源系统的实现

    Java毕业设计实战之食品溯源系统的实现 总体方案设计 食品溯源系统是一个涉及到供应链的系统,其主要功能是通过一系列的技术手段,让消费者了解所消费的食品的生产、加工、运输等各个环节的信息,保证消费者的健康和权益。因此,食品溯源系统的主要模块有:数据录入模块,数据存储模块,数据查询模块,数据展示模块等。 在本项目中,我们采用的技术方案是SpringBoot+M…

    Java 2023年5月31日
    00
  • Java List分页功能实现代码实例

    以下是关于“Java List分页功能实现代码实例”的详细攻略: 一、概述 在实际应用中,我们通常需要从数据库或其他数据源中获取大量数据,并将其以分页的方式展示在页面中,以提升用户体验和性能。Java中的List是一种常用的数据结构,因此实现List分页功能是比较常见的需求。本文将介绍如何实现Java List分页功能,并提供代码示例。 二、基本思路 Jav…

    Java 2023年6月15日
    00
  • 详解Spring Boot 异步执行方法

    下面是详解SpringBoot异步执行方法的完整攻略。 1. 什么是异步执行? 在程序执行中,如果某个方法耗时比较长,会阻塞当前线程,导致整个程序变得缓慢。为了解决这个问题,我们可以采用异步执行的方式,将耗时操作交给另一个线程去执行,这样就不会阻塞当前线程,提高程序执行效率。 2. SpringBoot异步执行方法的实现方式 SpringBoot提供了一种简…

    Java 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部