java 如何在不使用Spring Security的情况下在Sping Boot 上进行身份验证?

xt0899hw  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(172)

问题是:我需要在不使用Spring Security的情况下实现身份验证机制。Stack:Sping Boot + React。我首先尝试在控制器中注册会话ID,并使用HashMap将会话ID绑定到用户名。当用户注册时,他们的会话ID将被记录并绑定到他们的用户名。如果用户退出,则会话将从Map中删除。
此外,我提出的唯一解决方案是使用JavaScript询问服务器HashMap中是否缺少会话ID,但结果证明这种方法是无效的。**
必须实现以下目标:如果用户在浏览器的第二个页签进入这个站点,那么如果他在第一个页签登录,他会自动登录到第二个页签,而且如果用户在第一个页签注销,那么第二个页签应该自动注销。
我该怎么做呢?
我的控制者:

import com.cleanyco.weblab4backend.model.User;
import com.cleanyco.weblab4backend.repository.UserRepository;
import com.cleanyco.weblab4backend.util.MD5PasswordEncoder;
import com.google.gson.Gson;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

@RestController
public class UserController {
    private static final Logger logger = Logger.getLogger(UserController.class.getName());
    private final UserRepository userRepository;

    public UserController(@Autowired UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    private final Map<String, String> activeSessions = new HashMap<>();

    public String identificateSession(String sessionID) {
        for (Map.Entry<String, String> userSession : activeSessions.entrySet()) {
            if (userSession.getKey().equals(sessionID)) {
                return userSession.getValue();
            }
        }
        return null;
    }

    @CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
    @PostMapping("/signup")
    public ResponseEntity<?> signup(HttpSession session, @RequestBody User user) {
        User existingUser = userRepository.findUserByUsername(user.getUsername());
        if (existingUser == null) {
            logger.info("User wasn't found. Registering a new one...");
            activeSessions.put(session.getId(), user.getUsername());
            logger.info("Registered an active session. User: " + user.getUsername() + "; SessionID: " + session.getId());
            user.setPassword(MD5PasswordEncoder.hash(user.getPassword()));
            userRepository.save(user);
            logger.info("User was successfully saved");
            return new ResponseEntity<>(HttpStatus.OK);
        } else {
            logger.info("User with the same name already exists");
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

    @CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
    @PostMapping("/login")
    public ResponseEntity<?> login(HttpSession session, @RequestBody User user) {
        User existingUser = userRepository.findUserByUsername(user.getUsername());
        if (existingUser != null) {
            String userPassword = user.getPassword();
            String hashedPassword = MD5PasswordEncoder.hash(userPassword);
            if (existingUser.getPassword().equals(hashedPassword)) {
                logger.info("User successfully logged in");
                String activeUser = identificateSession(session.getId());
                if (activeUser == null) {
                    activeSessions.put(session.getId(), user.getUsername());
                }
                return new ResponseEntity<>(HttpStatus.OK);
            } else {
                logger.info("Invalid password was provided");
                return new ResponseEntity<>(HttpStatus.FORBIDDEN);
            }
        } else {
            logger.info("User not found");
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }
    
    private static final Gson gson = new Gson();
    @CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
    @GetMapping(value = "/checksession", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> getActiveSession(HttpSession session) {
        if (identificateSession(session.getId()) != null) {
            String username = identificateSession(session.getId());
            User user = userRepository.findUserByUsername(username);
            return ResponseEntity.ok(gson.toJson(user));
        } else {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

    @CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
    @GetMapping("/logout")
    public ResponseEntity<?> logout(HttpSession session) {
        String exitUser = identificateSession(session.getId());
        if (activeSessions.remove(exitUser) == null) {
            logger.info("An error occurred while logging out the user: user already logged out");
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        } else {
            activeSessions.remove(session.getId());
            logger.info("User was successfully logged out. User: " + exitUser + "; SessionID: " + session.getId());
            return new ResponseEntity<>(HttpStatus.OK);
        }
    }
}```
yfwxisqw

yfwxisqw1#

要使用登录/注销同步处理多个浏览器窗口,请执行以下操作。
1.当用户登录时,在浏览器本地存储中设置一个标志。
1.用户注销时,重置/清除本地存储中的标志。
1.每次UI应用程序启动时,检查本地存储中的标志。如果设置了标志,则假定用户已登录,否则显示登录页面。
1.要同步用户注销,您需要实现一个方法,该方法将频繁轮询本地存储值,如果重置标记,则假定用户从另一个选项卡注销,并在当前选项卡中注销。

相关问题