SpringBoot整合JWT实现安全认证

Spring Boot 整合 JWT 实现一个安全的Restful 接口?

JWT 是一种用于身份验证和授权的开放标准(RFC 7519),它允许使用签名验证和信息加密来传输数据。集成 JSON Web Token(JWT)到 Spring Boot 以实现安全的 RESTful 接口是一种常见的做法。下面是一个简单的步骤,展示如何在 Spring Boot 中整合 JWT。

第一步、添加POM依赖

首先,需要添加JWT相关依赖到POM文件中。这里需要根据自己项目的版本对JWT版本做对应的适配,否则可能会出现版本差异导致相关功能不能用的情况出现。

复制代码
<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>

创建JWT工具类

需要创建一个JWT的通用工具类,完成JWT的创建与解析操作,同时需要完成认证的签发、验证令牌等操作。如下所示。

复制代码
@Component
public class JwtUtils {

    private static final String SECRET_KEY = "yourSecretKey";
    private static final long EXPIRATION_TIME = 86400000; // 24 hours

    public String generateToken(String username) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME);

        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expiryDate)
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }

    public String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();

        return claims.getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }
}

注意这里需要指定对应的秘钥以及过期时间等信息。

创建接口安全配置类

引入SpringSecurity的POM依赖

复制代码
<!-- spring security 安全认证 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

创建配置类

创建一个 Spring Security 配置类,配置认证和授权规则,并且集成 JWT。

复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // 配置用户认证信息
        auth.inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("password")).roles("ADMIN")
                .and()
                .withUser("user").password(passwordEncoder().encode("password")).roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/authenticate").permitAll()
            .antMatchers(HttpMethod.GET, "/api/**").hasAnyRole("USER", "ADMIN")
            .antMatchers(HttpMethod.POST, "/api/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }

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

需要注意,这里提供了一个

UsernamePasswordAuthenticationFilter的拦截器,这个拦截器就是用来进行请求拦截进行判断处理的。

复制代码
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
    @Autowired
    private JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException{
              // 具体使用 
              // 1、通过Request请求获取到请求头中的Token信息
              // 2、将Token信息传入到JwtUtils进行认证,如果通过则继续调用
              // 如果拦截返回未授权信息
        chain.doFilter(request, response);
    }
}

创建认证请求实体对象

创建一个通用的认证请求以及相应对象来进行测试调用。

复制代码
public class AuthRequest {

    private String username;
    private String password;

    // getters and setters
}

public class AuthResponse {

    private final String token;

    public AuthResponse(String token) {
        this.token = token;
    }

    // getter
}

创建 REST 控制器

创建 REST 控制器来处理认证请求,并且使用 JWT 工具类来生成令牌。

复制代码
@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @PostMapping("/authenticate")
    public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthRequest authenticationRequest) throws Exception {
        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));
        } catch (AuthenticationException e) {
            throw new Exception("Incorrect username or password", e);
        }

        final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
        final String token = jwtUtils.generateToken(userDetails.getUsername());

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

创建完成之后,就可以通过接口调用认证接口,然后获取到认证的Token令牌,然后根据访问令牌来进行身份验证,这样就可以保证接口调用的安全性。

相关推荐
毕设源码-朱学姐5 小时前
【开题答辩全过程】以 工厂能耗分析平台的设计与实现为例,包含答辩的问题和答案
java·vue.js
Spring AI学习7 小时前
Spring AI深度解析(9/50):可观测性与监控体系实战
java·人工智能·spring
java1234_小锋7 小时前
Spring IoC的实现机制是什么?
java·后端·spring
xqqxqxxq8 小时前
背单词软件技术笔记(V2.0扩展版)
java·笔记·python
消失的旧时光-19438 小时前
深入理解 Java 线程池(二):ThreadPoolExecutor 执行流程 + 运行状态 + ctl 原理全解析
java·开发语言
哈哈老师啊8 小时前
Springboot学生综合测评系统hxtne(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·数据库·spring boot
4311媒体网8 小时前
帝国cms调用文章内容 二开基本操作
java·开发语言·php
zwxu_9 小时前
Nginx NIO对比Java NIO
java·nginx·nio
唐僧洗头爱飘柔95279 小时前
【软考:程序员(01)】如何考得程序员证书?本片知识点:操作系统基本概念、操作系统的分类、进程管理、三态模型、信号量机制、同步与互斥模型
程序员·软考·实时操作系统·信号量机制·批处理操作系统·三态模型·同步与互斥模型
可观测性用观测云10 小时前
Pyroscope Java 接入最佳实践
java