Springboot集成Spring Security实现JWT认证的步骤详解

针对“Springboot集成Spring Security实现JWT认证的步骤详解”这个主题,我将从以下几个方面给出详细的解答:

  1. Spring Security、JWT和Spring Boot的基本概念介绍

  2. JWT认证的基本过程及原理

  3. Springboot集成Spring Security实现JWT认证的步骤详解

  4. 两个示例:

a. 基于用户名密码认证,返回JWT

b. 基于JWT认证,保护REST API接口

以下是详细的内容:

一、Spring Security、JWT和Spring Boot的基本概念介绍

1. Spring Security

Spring Security 是 Spring 提供的安全框架,它能够帮助我们在 Spring 应用中实现许多安全功能,例如:身份验证、授权、防止 XSS 攻击、CSRF 攻击等。

2. JWT

JWT ( JSON Web Token ) 是一个基于 JSON 的开放标准(RFC 7519),用于在两个实体之间传递安全信息。JWT通常被用来实现身份认证和授权。当用户通过认证时,系统会生成一段 JWT,将其发送给客户端。客户端在请求时需要将该 JWT 传给服务端,服务端可以解析 JWT 来校验身份信息的合法性。

3. Spring Boot

Spring Boot是一个基于Spring框架的快速开发开发框架。它可以帮助开发者快速搭建Spring应用,同时提供了很多开箱即用的组件(例如:Tomcat、Jackson、Hibernate、Spring Data、Spring Security等),减少了开发者的开发成本。

二、JWT认证的基本过程及原理

JWT 由三部分组成:头部、载荷和签名。头部和载荷使用 Base64 编码,编码后的字符串在 HTTP 响应头的 Authorization 字段或者 HTTP 请求体中传递。签名用于校验 JWT 的合法性。

JWT 认证的基本过程如下:

  1. 客户端通过用户名和密码向服务端请求认证。

  2. 服务端校验用户名和密码,如果校验通过则生成一个 JWT。

  3. 服务端将生成的 JWT 发送给客户端。

  4. 客户端在每次请求中需要在 Authorization 字段中携带 JWT。

  5. 服务端会在每次接收到请求时校验 JWT 的合法性,如果合法则允许请求,否则返回 401 错误码。

三、Springboot集成Spring Security实现JWT认证的步骤详解

1. 添加Spring Security及JWT依赖

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

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

2. 编写认证过滤器

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    public static final String JWT_SECRET = "mysecretkey";
    public static final long JWT_EXPIRATION_TIME = 864_000_000; // 10 days

    private final AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        try {
            UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);

            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            creds.getUsername(),
                            creds.getPassword(),
                            new ArrayList<>()
                    )
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String token = Jwts.builder()
                .setSubject(((User) authResult.getPrincipal()).getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, JWT_SECRET.getBytes())
                .compact();
        response.addHeader("Authorization", "Bearer " + token);
    }
}

3. 添加Security配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

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

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilterBefore(new JWTAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}

四、示例

a. 基于用户名密码认证,返回JWT

下面是一个基于用户名密码认证,返回JWT的例子。

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody UserCredentials credentials) throws AuthenticationException {
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(
            credentials.getUsername(),
            credentials.getPassword()
        )
    );

    SecurityContextHolder.getContext().setAuthentication(authentication);

    String token = Jwts.builder()
        .setSubject(credentials.getUsername())
        .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME))
        .signWith(SignatureAlgorithm.HS512, JWT_SECRET.getBytes())
        .compact();

    return ResponseEntity.ok(new JwtResponse(token));
}

b. 基于JWT认证,保护REST API接口

下面是一个基于JWT认证,保护REST API接口的例子。

@GetMapping("/hello")
public String hello(HttpServletRequest request) {
    String header = request.getHeader("Authorization");
    String token = header.replace("Bearer ", "");

    Jws<Claims> jws = Jwts.parser().setSigningKey(JWT_SECRET.getBytes()).parseClaimsJws(token);
    String username = jws.getBody().getSubject();

    return "Hello " + username + "!";
}

以上就是关于“Springboot集成Spring Security实现JWT认证的步骤详解”的完整攻略,希望可以帮助到你。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot集成Spring Security实现JWT认证的步骤详解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java Object定义三个点实现代码

    关于“Java Object定义三个点实现代码”的攻略,我来给您详细解释一下。 什么是 Java Object 定义三个点? Java Object 定义三个点是指 Java 对象中定义的三个点:hashCode()、equals() 和 toString()。这三个点是 Java 的基本组成部分,很多情况下需要通过它们来实现对象的比较、打印和哈希等操作。 …

    Java 2023年5月26日
    00
  • JSP+MySQL实现网站的登录与注册小案例

    JSP+MySQL实现网站的登录与注册小案例,需要以下步骤完成: 确定数据库表 设计一个用户表来存储用户名和密码,例如: CREATE TABLE user( uid INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20) NOT NULL UNIQUE, password VARCHAR(30) NOT N…

    Java 2023年6月15日
    00
  • mybatis实现获取入参是List和Map的取值

    对于MyBatis,我们可以通过Mapper接口的方法的入参类型来传递参数。如果我们需要传递List或者Map类型的参数,该如何处理呢?下面我们来一一讲解。 传递List类型的参数 当我们需要将一个List类型的参数传递给Mapper接口的方法时,我们可以采用@Param注解的方式将参数进行命名,如下所示: public interface UserMapp…

    Java 2023年5月20日
    00
  • Java File类的详解及简单实例

    Java File类的详解及简单实例 简介 Java中的File类是一个用于操作文件和文件夹的类,可以用于检查文件和文件夹的状态、进行文件和文件夹的删除、重命名等操作。File类中包含的方法较多,它与Java IO的输入输出流中的类相互支持,是进行Java操作文件的重要一环。 File类的构造函数 File(String pathname) 用指定的路径na…

    Java 2023年5月20日
    00
  • Java数组动态增加容量过程解析

    Java数组本质上是一个定长的数据结构,在创建过程中需要指定数组的长度。如果在程序执行过程中需要动态地增加数组的容量,就需要用到Java中的动态数组技术。 Java动态数组的实现方式是:创建一个新数组,并将原数组的元素拷贝到新数组中,同时增加新元素。实现过程如下: 判断当前元素个数是否等于数组长度,如果等于,则需要创建新数组。 计算新数组的长度,一般是将原数…

    Java 2023年5月26日
    00
  • 什么是类路径?

    以下是关于类路径的完整使用攻略: 什么是类路径? 类路径是Java虚拟机(JVM)用来查找类文件的路径。当JVM需要加载一个类时它会在类路径中查找该类的字节码文件。类路径可以包含多个路径,每个路径之间用分隔符(如冒号或分号)分隔。 类路径的设置 类路径可以通过以下方式进行设置: 命令行参数:可以通过命令行参数设置类路径。例如,以下是一个设置类路径的命令: b…

    Java 2023年5月12日
    00
  • java后台批量下载文件并压缩成zip下载的方法

    请允许我给出完整的“java后台批量下载文件并压缩成zip下载的方法”的攻略: 1. 需求分析 首先,我们需要明确需求,由于是后台批量下载文件并压缩成zip下载,所以我们需要考虑以下几个方面: 获取文件路径列表 批量下载文件 压缩成zip文件 提供zip文件下载 2. 操作步骤 2.1 获取文件路径列表 我们可以通过一个方法获取文件路径列表,该方法需要传入文…

    Java 2023年5月19日
    00
  • mybatis实现对数据的增删查改实例详解

    下面我将详细讲解“mybatis实现对数据的增删查改实例详解”的完整攻略。 1. Mybatis介绍 Mybatis是一种基于Java的数据持久化框架,它通过XML或注解的方式将Java对象映射到数据库中的数据表中,从而实现对数据库的操作。 2. Mybatis的基本使用 2.1 配置文件 Mybatis的配置文件包含了以下几个主要部分: configura…

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