📜  Spring Boot-具有JWT的OAuth2(1)

📅  最后修改于: 2023-12-03 14:47:33.192000             🧑  作者: Mango

Spring Boot-具有JWT的OAuth2

简介

本文介绍如何使用Spring Boot框架实现具有JWT(JSON Web Token)的OAuth2(开放授权)功能。OAuth2是一种用于安全保护API的授权框架,JWT是一种用于在各方之间安全传输声明的开放标准。

本教程将引导您通过以下步骤配置您的Spring Boot应用程序,以使用JWT和OAuth2进行身份验证和授权。

步骤
1. 添加依赖

首先,在您的Spring Boot项目的pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<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>
2. 配置OAuth2

application.propertiesapplication.yml文件中配置OAuth2相关属性:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: <YOUR_GOOGLE_CLIENT_ID>
            client-secret: <YOUR_GOOGLE_CLIENT_SECRET>
            redirect-uri: <YOUR_REDIRECT_URI>
          github:
            client-id: <YOUR_GITHUB_CLIENT_ID>
            client-secret: <YOUR_GITHUB_CLIENT_SECRET>
            redirect-uri: <YOUR_REDIRECT_URI>
3. 创建JWT工具类

创建一个JwtUtils类来处理JWT的生成和验证:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtUtils {

    private final String jwtSecret = "<YOUR_JWT_SECRET>";
    private final long jwtExpirationMs = 86400000; // 24小时

    public String generateJwtToken(Authentication authentication) {
        UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
        return Jwts.builder()
                .setSubject(userPrincipal.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(new Date().getTime() + jwtExpirationMs))
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }

    public String getUsernameFromJwtToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
        return claims.getSubject();
    }

    public boolean validateJwtToken(String token) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            // 处理验证失败的异常
        }

        return false;
    }
}
4. 创建OAuth2回调控制器

创建一个控制器来处理OAuth2回调请求并生成JWT令牌:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@RequestMapping("/oauth2/callback")
public class OAuth2CallbackController {

    @Autowired
    private JwtUtils jwtUtils;

    @GetMapping("/google")
    public void handleGoogleCallback(HttpServletRequest request, HttpServletResponse response) {
        handleCallback(request, response);
    }

    @GetMapping("/github")
    public void handleGithubCallback(HttpServletRequest request, HttpServletResponse response) {
        handleCallback(request, response);
    }

    private void handleCallback(HttpServletRequest request, HttpServletResponse response) {
        String jwtToken = jwtUtils.generateJwtToken(getAuthentication());
        // 将JWT令牌返回给客户端
        // markdown: `response.setHeader("Authorization", "Bearer " + jwtToken);`
        response.setHeader("Authorization", "Bearer " + jwtToken);
        // 重定向到应用程序的URL
        // markdown: `response.sendRedirect(<YOUR_APP_URL>);`
        response.sendRedirect(<YOUR_APP_URL>);
    }

    private Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }
}
5. 创建安全配置

创建一个安全配置类来为您的应用程序启用Spring Security和OAuth2:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

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

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/oauth2/callback/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .defaultSuccessUrl("/oauth2/callback/google")
                .and()
            .oauth2Login()
                .defaultSuccessUrl("/oauth2/callback/github");
    }
}
结论

本教程介绍了如何在Spring Boot应用程序中使用JWT和OAuth2进行身份验证和授权。通过完成以上步骤,您将能够实现安全的API访问和授权。

请根据您的实际需求,修改和适配上述代码片段。