springboot篇-基于session和github-oauth2实现登录注册验证

2024.8.25更新文档:主要是增添了GitHubOAuth板块的服务层,把控制层的逻辑板块转移到了服务层,同时加入了Exception类的内容,把错误控制到自己的intercepter中。

本文简介

本文讲解,在不使用SpringSecurity的情况下,只用简单的方式实现一个简单版本的登录注册验证功能。依靠的方式是在后端存贮session表,然后让前端的localstorage存贮sessionId,用sessionId来session表中获取user的信息。

同时借助session表实现了利用GitHub的oauth2第三方登录。

基本思路

使用session表与User表通过UserId相连接,登录注册时给前端返回sessionId,然后前端用sessionId作为RequestParam传给后端,换取用户数据。

框架版本

springboot3 + gradle-kotlin + Java17

核心依赖

  • Spring Web
  • JDBC
  • Spring Data JPA
  • MySQL Driver
  • Okhttp
  • Gson

开源地址

后端地址:springboot-session-github-oauth

前端地址:vite-session-github-oauth

主要学习点

注解@ControllerAdvise

@ControllerAdvice
public class ExceptionHandlerControllerAdvice {

    // 处理应用程序中发生的所有异常
    @ExceptionHandler(value = {Throwable.class})
    public ResponseEntity<ApiResponse<String>> handleException(Throwable ex) {
        // 创建一个响应对象,返回给客户端
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setMessage(ex.getMessage());  // 设置异常消息

        HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;  // 默认返回500内部服务器错误

        // 如果异常是BaseHttpException类型,则使用该异常中的HTTP状态码
        if (ex instanceof BaseHttpException baseHttpException) {
            httpStatus = baseHttpException.getHttpStatus();  // 获取自定义的HTTP状态码
            apiResponse.setStatus(httpStatus);  // 设置响应状态
        }

        // 返回带有状态码的响应实体
        return ResponseEntity.status(httpStatus).body(apiResponse);
    }
}

ExceptionHandlerControllerAdvice类是一个全局异常处理器,用于捕获和处理应用程序中发生的异常,并返回适当的响应。

  • handleException(Throwable ex): 这是一个异常处理方法,捕获所有类型的异常。
    • 参数:
      • ex: 捕获到的异常对象。
    • 返回值: 返回一个 ResponseEntity,包含了异常的消息和状态码。默认情况下,状态码为500(内部服务器错误)。如果捕获的异常是 BaseHttpException 类型,则使用该异常中定义的HTTP状态码。

Okhttp连接

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public void redirect(@RequestParam("code") String requestToken,
                     @RequestParam(required = false, value = "state") String state,
                     HttpServletResponse httpServletResponse) throws IOException {

    // 创建 OkHttpClient 实例,用于发送 HTTP 请求
    OkHttpClient client = new OkHttpClient();

    // 构建请求体参数,存储在 HashMap 中
    HashMap<String, String> bodyMap = new HashMap<>();
    bodyMap.put("client_id", clientId);  // 客户端 ID
    bodyMap.put("client_secret", clientSecret);  // 客户端密钥
    bodyMap.put("code", requestToken);  // 授权码
    bodyMap.put("redirect_uri", redirectUri);  // 重定向 URI
    bodyMap.put("grant_type", "authorization_code");  // 授权类型

    // 将请求体参数转换为 JSON 格式的字符串
    String reqBodyJson = new Gson().toJson(bodyMap);
    // 创建请求体
    RequestBody requestBody = RequestBody.create(reqBodyJson, JSON_MEDIA_TYPE);
    // 构建 HTTP 请求对象,设置目标 URL、请求方法、请求头和请求体
    Request request = new Request.Builder()
            .url(GITHUB_TOKEN_URL)
            .post(requestBody)
            .header("Accept", "application/json")
            .build();

    try (Response response = client.newCall(request).execute()) {
        // 判断响应是否成功
        if (!response.isSuccessful()) {
            handleError(httpServletResponse, "Failed to get access token");  // 处理错误响应
            return;
        }

        // 解析 JSON 响应以提取 access token
        assert response.body() != null;
        String responseBody = response.body().string();
        JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
        String accessToken = jsonObject.get("access_token").getAsString();

        // 使用 access token 处理用户信息
        handleUserInfo(accessToken, state, httpServletResponse, client);

    } catch (IOException e) {
        // 处理过程中出现异常,记录错误日志并返回内部服务器错误
        logger.error("Error during OAuth2 redirect handling", e);
        handleError(httpServletResponse, "Internal server error");
    }
}

OkHttp 是一个现代化的 HTTP 客户端库,支持同步和异步请求,能够轻松处理网络操作和数据传输。

  • OkHttpClient:用于创建和执行 HTTP 请求的客户端。
  • Request:表示 HTTP 请求的类。可以使用 Request.Builder 进行构建,设置 URL、请求方法、请求头和请求体。
  • RequestBody:HTTP 请求的请求体,可以用来发送 JSON、表单数据等。
  • Response:HTTP 响应的类,包含了响应的状态码、响应体等信息。

代码实现

数据表设计

UserDO 用户数据表

package com.example.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "users")

public class UserDO {
    @Id
    @Column(name = "user_id")
    private String userId;

    @Column
    private String username;

    @Column
    private String password;

    @Column
    private String githubLoginName;
}

SessionDO session表

package com.example.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "session")
public class SessionDO {
    @Id
    @Column(name = "session_id")
    private String sessionId;

    @Column
    private String userId;
 }

拦截器

BaseHttpException 捕获异常

package com.example.exception;

import org.springframework.http.HttpStatus;

public interface BaseHttpException {
    HttpStatus getHttpStatus();
}

各类Exception

package com.example.exception;

import org.springframework.http.HttpStatus;

public class ForbiddenException extends RuntimeException implements BaseHttpException {
    public ForbiddenException(String message) {
        super(message);
    }

    @Override
    public HttpStatus getHttpStatus() {
        return HttpStatus.FORBIDDEN;
    }
}

package com.example.exception;

import org.springframework.http.HttpStatus;

public class SessionNotFoundException extends RuntimeException implements BaseHttpException{
    public SessionNotFoundException(String message) {
        super(message);
    }

    @Override
    public HttpStatus getHttpStatus() {
        return HttpStatus.UNAUTHORIZED;
    }
}

package com.example.exception;

import org.springframework.http.HttpStatus;

public class UserAlreadyExistsException extends RuntimeException implements BaseHttpException{
    public UserAlreadyExistsException(String message) {
        super(message);
    }

    @Override
    public HttpStatus getHttpStatus() {
        return HttpStatus.CONFLICT;
    }
}

package com.example.exception;

import org.springframework.http.HttpStatus;

public class UserNotFoundException extends RuntimeException implements BaseHttpException {
    public UserNotFoundException(String message) {
        super(message);
    }

    @Override
    public HttpStatus getHttpStatus() {
        return HttpStatus.NOT_FOUND;
    }
}

ExceptionHandlerControllerAdvice 实现ControllerAdvise

package com.example.interceptor;

import com.example.exception.BaseHttpException;
import com.example.response.ApiResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ExceptionHandlerControllerAdvice {
    @ExceptionHandler(value = {Throwable.class})
    public ResponseEntity<ApiResponse<String>> handleException(Throwable ex) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setMessage(ex.getMessage());
        HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        if (ex instanceof BaseHttpException baseHttpException) {
            httpStatus= baseHttpException.getHttpStatus();
            apiResponse.setStatus(httpStatus);
        }
        return ResponseEntity.status(httpStatus).body(apiResponse);
    }
}

服务层

userService 负责User的密码验证、增加密码、绑定github的逻辑

package com.example.service;

import com.example.dto.UserDTO;
import com.example.entity.UserDO;
import com.example.exception.ForbiddenException;
import com.example.exception.UserAlreadyExistsException;
import com.example.exception.UserNotFoundException;
import com.example.mapper.UserRepository;
import com.example.model.UserRequest;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    @Transactional
    public void authenticate(String username, String password) {
        UserDO userDO = userRepository.findByUsername(username);
        if (userDO == null) {
            throw new UserNotFoundException("User not found with username: " + username);
        }
        if (!userDO.getPassword().equals(password)) {
            throw new ForbiddenException("Wrong password with username: " + username);
        }
    }

    @Transactional
    public void checkUserExists(String username) {
        UserDO userDO = userRepository.findByUsername(username);
        if (userDO != null) {
            throw new UserAlreadyExistsException("User already exists with username: " + username);
        }
    }

    public UserDTO saveUser(UserRequest userRequest) {
        UserDO userDO = new UserDO();
        UUID uuid = UUID.randomUUID();
        userDO.setUserId(uuid.toString());
        userDO.setUsername(userRequest.getUsername());
        userDO.setPassword(userRequest.getPassword());
        userDO.setGitHubLoginName(null);
        userRepository.save(userDO);
        return UserDTO.newFromDO().apply(userDO);
    }

    public void saveGitHubUser(String userId, String username, String githubLoginName) {
        UserDO userDO = new UserDO();
        userDO.setUserId(userId);
        userDO.setUsername(username);
        userDO.setPassword(null);
        userDO.setGitHubLoginName(githubLoginName);
        userRepository.save(userDO);
    }

    public void addPassword(String userId, String password) {
        UserDO userDO = userRepository.findByUserId(userId);
        userDO.setPassword(password);
        userRepository.save(userDO);
    }

    public void addGitHubLoginName(String userId, String githubLoginName) {
        UserDO userDO = userRepository.findByUserId(userId);
        userDO.setGitHubLoginName(githubLoginName);
        userRepository.save(userDO);
    }

    public UserDTO findUserByUsername(String username) {
        UserDO userDO = userRepository.findByUsername(username);
        return UserDTO.newFromDO().apply(userDO);
    }

    public UserDTO findUserByUserId(String userId) {
        UserDO userDO = userRepository.findByUserId(userId);
        return UserDTO.newFromDO().apply(userDO);
    }

}

sessionService 负责session的增删改查

package com.example.service;

import com.example.entity.SessionDO;
import com.example.exception.SessionNotFoundException;
import com.example.mapper.SessionRepository;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SessionService {

    @Autowired
    SessionRepository sessionRepository;

    @Transactional
    public void SessionExists(SessionDO sessionDO) {
        if (sessionDO == null) {
            throw new SessionNotFoundException("Session not found");
        }
    }

    public void saveSession(SessionDO sessionDO) {
        sessionRepository.save(sessionDO);
    }

    public void deleteSession(SessionDO sessionDO) {
        sessionRepository.delete(sessionDO);
    }

    @Transactional
    public SessionDO getSessionBySessionId(String sessionId) {
        SessionDO sessionDO = sessionRepository.findBySessionId(sessionId);
        SessionExists(sessionDO);
        return sessionDO;
    }

}

GitHubOAuthService 负责了authorize和redirect中的核心逻辑getAccessToken和processUserInfo

package com.example.service;

import com.example.exception.OAuth2TokenRetrievalException;
import com.example.exception.UserInfoProcessingException;
import com.example.manager.BaseAuthManager;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import jakarta.transaction.Transactional;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.UUID;

@Service
public class GitHubOAuthService {
    private static final Logger logger = LoggerFactory.getLogger(GitHubOAuthService.class);
    private static final String GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
    private static final String GITHUB_USER_API_URL = "https://api.github.com/user";
    private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json");

    @Value("${github.client-id}")
    private String clientId;

    @Value("${github.client-secret}")
    private String clientSecret;

    @Value("${github.redirect-uri}")
    private String redirectUri;

    @Autowired
    private BaseAuthManager authManager;

    @Autowired
    private UserService userService;

    public String getClientId() {
        return clientId;
    }

    public String getRedirectUri() {
        return redirectUri;
    }

    @Transactional
    public String getAccessToken(String requestToken) {
        OkHttpClient client = new OkHttpClient();

        HashMap<String, String> bodyMap = new HashMap<>();
        bodyMap.put("client_id", clientId);
        bodyMap.put("client_secret", clientSecret);
        bodyMap.put("code", requestToken);
        bodyMap.put("redirect_uri", redirectUri);
        bodyMap.put("grant_type", "authorization_code");

        String reqBodyJson = new Gson().toJson(bodyMap);
        RequestBody requestBody = RequestBody.create(reqBodyJson, JSON_MEDIA_TYPE);
        Request request = new Request.Builder()
                .url(GITHUB_TOKEN_URL)
                .post(requestBody)
                .header("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new OAuth2TokenRetrievalException("Failed to get access token");
            }

            assert response.body() != null;
            String responseBody = response.body().string();
            JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
            return jsonObject.get("access_token").getAsString();
        } catch (IOException e) {
            logger.error("Error during OAuth2 token retrieval", e);
            throw new OAuth2TokenRetrievalException("Error during OAuth2 token retrieval", e);
        }
    }

    @Transactional
    public String processUserInfo(String accessToken, String state) {
        OkHttpClient client = new OkHttpClient();
        Request userInfoRequest = new Request.Builder()
                .url(GITHUB_USER_API_URL)
                .header("Authorization", "token " + accessToken)
                .build();

        try (Response userInfoResponse = client.newCall(userInfoRequest).execute()) {
            if (!userInfoResponse.isSuccessful()) {
                throw new UserInfoProcessingException("Failed to get user info");
            }

            assert userInfoResponse.body() != null;
            String userInfoResponseBody = userInfoResponse.body().string();
            String githubLoginName = findTextFromBody(userInfoResponseBody, "login");

            if (state == null) {
                String name = findTextFromBody(userInfoResponseBody, "name");
                String sessionId = findTextFromBody(userInfoResponseBody, "id");
                String userId = UUID.randomUUID().toString();
                authManager.saveSession(sessionId, userId);
                userService.saveGitHubUser(userId, name, githubLoginName);
                return sessionId;
            } else {
                String userId = authManager.getUserId(state);
                userService.addGitHubLoginName(userId, githubLoginName);
                return null;
            }
        } catch (IOException e) {
            logger.error("Error during OAuth2 token retrieval", e);
            throw new UserInfoProcessingException("Error during user info handling", e);
        }
    }

    private String findTextFromBody(String body, String text) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(body);
            JsonNode nameNode = rootNode.path(text);
            return !nameNode.isMissingNode() ? nameNode.asText() : null;
        } catch (Exception e) {
            logger.error("Error parsing JSON response", e);
            return null;
        }
    }
}

控制层

authController 负责登录、注册、验证

package com.example.controller;

import com.example.dto.UserDTO;
import com.example.manager.BaseAuthManager;
import com.example.model.UserRequest;
import com.example.response.ApiResponse;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
@CrossOrigin
public class AuthController {
    private final UserService userService;
    private final BaseAuthManager authManager;

    @Autowired
    public AuthController(UserService userService, BaseAuthManager authManager) {
        this.userService = userService;
        this.authManager = authManager;
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ApiResponse<String> loginUser(@RequestBody UserRequest userRequest) {
        String username = userRequest.getUsername();
        String password = userRequest.getPassword();
        userService.authenticate(username, password);
        UserDTO userDTO = userService.findUserByUsername(username);
        String userId = userDTO.getUserId();
        String sessionId = authManager.createSession(userId);
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        apiResponse.setMessage("Successfully logged in");
        apiResponse.setData(sessionId);
        return apiResponse;
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public ApiResponse<String> registerUser(@RequestBody UserRequest userRequest) {
        String username = userRequest.getUsername();
        userService.checkUserExists(username);
        UserDTO userDTO = userService.saveUser(userRequest);
        String userId = userDTO.getUserId();
        String sessionId = authManager.createSession(userId);
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        apiResponse.setMessage("User registered successfully");
        apiResponse.setData(sessionId);
        return apiResponse;
    }

    @RequestMapping(value = "/home", method = RequestMethod.GET)
    public ApiResponse<String> home(@RequestParam String sessionId) {
        String userId = authManager.getUserId(sessionId);
        UserDTO userDTO = userService.findUserByUserId(userId);
        String username = userDTO.getUsername();
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        apiResponse.setMessage("Welcome, " + username);
        apiResponse.setData(username);
        return apiResponse;
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ApiResponse<String> logout(String sessionId) {
        authManager.deleteSessionBySessionId(sessionId);
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        apiResponse.setMessage("Successfully logged out");
        apiResponse.setData(null);
        return apiResponse;
    }
}

GitHubOAuthController 负责GiHubOAuth2的连接

package com.example.controller;

import com.example.manager.BaseAuthManager;
import com.example.service.UserService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import jakarta.servlet.http.HttpServletResponse;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.UUID;

@Controller
@RequestMapping("/oauth")
@CrossOrigin
public class GitHubOAuthController {
    private static final Logger logger = LoggerFactory.getLogger(GitHubOAuthController.class);
    private static final String GITHUB_AUTHORIZE_URL = "https://github.com/login/oauth/authorize";
    private static final String GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
    private static final String GITHUB_USER_API_URL = "https://api.github.com/user";
    private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json");

    @Value("${github.client-id}")
    private String clientId;

    @Value("${github.client-secret}")
    private String clientSecret;

    @Value("${github.redirect-uri}")
    private String redirectUri;

    @Autowired
    private BaseAuthManager authManager;

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/authorize", method = RequestMethod.GET)
    public void authorize(HttpServletResponse httpServletResponse, @RequestParam(required = false) String sessionId)
            throws IOException {
        String url = GITHUB_AUTHORIZE_URL
                + "?client_id=" + clientId
                + "&redirect_uri=" + redirectUri;

        if (sessionId != null && !sessionId.isEmpty()) {
            url += "&state=" + sessionId;
        }
        httpServletResponse.sendRedirect(url);
    }

    @RequestMapping(value = "/redirect", method = RequestMethod.GET)
    public void redirect(@RequestParam("code") String requestToken,
                         @RequestParam(required = false, value = "state") String state,
                         HttpServletResponse httpServletResponse) throws IOException {
        OkHttpClient client = new OkHttpClient();

        HashMap<String, String> bodyMap = new HashMap<>();
        bodyMap.put("client_id", clientId);
        bodyMap.put("client_secret", clientSecret);
        bodyMap.put("code", requestToken);
        bodyMap.put("redirect_uri", redirectUri);
        bodyMap.put("grant_type", "authorization_code");

        String reqBodyJson = new Gson().toJson(bodyMap);
        RequestBody requestBody = RequestBody.create(reqBodyJson, JSON_MEDIA_TYPE);
        Request request = new Request.Builder()
                .url(GITHUB_TOKEN_URL)
                .post(requestBody)
                .header("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                handleError(httpServletResponse, "Failed to get access token");
                return;
            }

            // 解析 JSON 响应以提取 access token
            assert response.body() != null;
            String responseBody = response.body().string();
            JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
            String accessToken = jsonObject.get("access_token").getAsString();

            handleUserInfo(accessToken, state, httpServletResponse, client);

        } catch (IOException e) {
            logger.error("Error during OAuth2 redirect handling", e);
            handleError(httpServletResponse, "Internal server error");
        }
    }

    private void handleUserInfo(String accessToken, String state, HttpServletResponse httpServletResponse, OkHttpClient client) throws IOException {
        Request userInfoRequest = new Request.Builder()
                .url(GITHUB_USER_API_URL)
                .header("Authorization", "token " + accessToken)
                .build();

        try (Response userInfoResponse = client.newCall(userInfoRequest).execute()) {
            if (!userInfoResponse.isSuccessful()) {
                handleError(httpServletResponse, "Failed to get user info");
                return;
            }

            // 将用户数据添加到模型中
            assert userInfoResponse.body() != null;
            String userInfoResponseBody = userInfoResponse.body().string();
            String githubLoginName = findTextFromBody(userInfoResponseBody, "login");
            if (state == null) { // 没有用户,只是登录
                String name = findTextFromBody(userInfoResponseBody, "name");
                String sessionId = findTextFromBody(userInfoResponseBody, "id");
                String userId = UUID.randomUUID().toString();
                authManager.saveSession(sessionId, userId);
                userService.saveGitHubUser(userId, name, githubLoginName);
                httpServletResponse.sendRedirect("http://localhost:5173/session/home?sessionId=" + sessionId);
            } else { //已有用户,配置第三方登录
                String userId = authManager.getUserId(state);
                userService.addGitHubLoginName(userId, githubLoginName);
                httpServletResponse.sendRedirect("http://localhost:5173/session/home?state=" + state);
            }

        } catch (IOException e) {
            logger.error("Error during user info handling", e);
            handleError(httpServletResponse, "Internal server error");
        }
    }

    private void handleError(HttpServletResponse httpServletResponse, String message) throws IOException {
        httpServletResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
    }

    private String findTextFromBody(String body, String text) {
        try {
            // 创建 ObjectMapper 实例
            ObjectMapper objectMapper = new ObjectMapper();
            // 解析 JSON 字符串
            JsonNode rootNode = objectMapper.readTree(body);
            // 获取 "name" 字段的值
            JsonNode nameNode = rootNode.path(text);
            if (!nameNode.isMissingNode()) {
                return nameNode.asText();
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("Error parsing JSON response", e);
            return null;
        }
    }
}

UserController - 关于用户增加密码、绑定github的设计

package com.example.controller;

import com.example.dto.UserDTO;
import com.example.manager.BaseAuthManager;
import com.example.model.AddPasswordRequest;
import com.example.response.ApiResponse;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
@CrossOrigin

public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private BaseAuthManager authManager;

    @RequestMapping(value = "/state", method = RequestMethod.GET)
    public ApiResponse<String> getUserState(@RequestParam String sessionId) {
        String userId = authManager.getUserId(sessionId);
        UserDTO userDTO = userService.findUserByUserId(userId);
        String password = userDTO.getPassword();
        String githubLoginName = userDTO.getGitHubLoginName();
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        if (password == null) {
            apiResponse.setMessage("User password is empty");
            apiResponse.setData("password");
            return apiResponse;
        }
        if (githubLoginName == null) {
            apiResponse.setMessage("User dont have github login name");
            apiResponse.setData("githubLoginName");
            return apiResponse;
        }
        apiResponse.setMessage("User already exists");
        apiResponse.setData("user");
        return apiResponse;
    }

    @RequestMapping(value = "/addPassword", method = RequestMethod.POST)
    public ApiResponse<String> addGitHubUser(@RequestParam String sessionId, @RequestBody AddPasswordRequest addPasswordRequest) {
        String userId = authManager.getUserId(sessionId);
        String password = addPasswordRequest.getPassword();
        userService.addPassword(userId, password);
        ApiResponse<String> apiResponse = new ApiResponse<>();
        apiResponse.setStatus(HttpStatus.OK);
        if (password == null) {
            apiResponse.setMessage("User password is empty");
        } else {
            apiResponse.setMessage("User password is added successfully");
        }
        return apiResponse;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值