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令牌,然后根据访问令牌来进行身份验证,这样就可以保证接口调用的安全性。

相关推荐
金銀銅鐵3 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
吴名氏.4 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
.痞老板.5 小时前
java ee--多线程(进阶)
java·java-ee
深入云栈6 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
wang_shu_mo_ran8 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
量化分析码农9 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
猫猫不是喵喵.9 小时前
从0到1创建一个微服务项目
java·数据库·微服务·1024程序员节
瑞雪兆丰年兮9 小时前
JavaWeb-day13-SpringBootWeb事务管理&AOP
java·开发语言·springboot·javaweb·事务·web·aop
曲径海盗9 小时前
Try-Except怎么用,3个追问解答在自动化下的应用
java·jvm·oracle
程序员cxuan10 小时前
讲真,智能路由这事儿,还得看基元律动
人工智能·后端·程序员