728x90
로그인
이전 포스팅에서 회원가입(Create)을 진행하였다면 로그인에서는 회원가입 된 데이터를 읽어서 적절한 요청과 응답을 해주면 된다.
1. UserController 작성
package board.controller;
import board.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import board.vo.UserVo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/joinForm") // 회원가입 페이지
public String join() {
return "/user/joinForm";
}
@PostMapping("/join/idCheck") // 중복 아이디 확인
@ResponseBody
public Map<String, Integer> idCheck(@RequestBody String username) throws Exception {
Map<String, Integer> map = new HashMap<>(); // 중복 아이디 결과를 담아줄 map 선언
map.put("count", userService.idCheck(username)); // 중복된 아이디의 갯수를 map에 put
return map; // 갯수 반환
}
@PostMapping("/join/insert") // 회원 가입
@ResponseBody
public String joinUser(@RequestBody UserVo userVo) throws Exception{
userService.insertUser(userVo);
return "success";
}
@GetMapping("/loginForm") // 로그인 페이지
public String login() {
return "/user/loginForm";
}
@PostMapping("/loginProc") // ID와 PW 일치 여부 확인
@ResponseBody
public boolean loginProc(@RequestBody UserVo userVo, HttpSession session) throws Exception {
String username = userService.loginProc(userVo); // 일치하는 회원의 id
if (username == null) { // 일치하는 회원의 아이디가 조회되지 않으면 세션 값을 설정하지 않고 리턴
return false;
}
userVo = userService.getUserInfo(username); // 회원의 id로 회원 정보를 조회하여 담아줌
session.setAttribute("signIn", userVo); // 회원의 세션 정보 생성 후 리턴
return true;
}
@GetMapping("/logout") // 로그아웃
public String logOut(HttpServletRequest request) {
HttpSession session = request.getSession(); // 전달받은 세션의 정보를 저장
session.invalidate(); // 세션 무효화
return "redirect:/";
}
}
- /user/loginForm 으로 요청이 들어올 시 로그인 페이지인 /user/loginForm.jsp를 반환한다.
- 로그인을 위해 아이디와 비밀번호를 POST 방식으로 HTTP BODY에 담아 전송받고, userService.loginProc의 인자로 userVo를 전달하여 결과값은 username을 반환받는다.
- loginProc에서는 전달받은 아이디와 비밀번호가 일치하는 회원을 DB에서 찾아 그 회원의 아이디를 반환하는데, null이라면 false를 반환하고 null이 아니라면 회원의 아이디로 getUserInfo 메서드를 이용해 회원 정보를 조회하여 userVo에 담아주고 signIn이라는 이름으로 세션을 생성한 후 리턴한다.
- user.js의 loginProc 메서드에서는 회원 정보를 반환받은지 여부를 판별하여 로그인을 시킬지 말지를 판단한다.
- 그리고 로그아웃은 session.invalidate() 메서드로 해당 세션을 무효화하는 방식으로 구현했다.
2. UserService, UserServiceImpl, UserMapper 작성
UserService.java
package board.service;
import board.vo.UserVo;
import org.springframework.stereotype.Service;
@Service
public interface UserService {
void insertUser(UserVo userVo) throws Exception;
String loginProc(UserVo userVo) throws Exception;
int idCheck(String username) throws Exception;
UserVo getUserInfo(String username);
}
UserServiceImpl.java
package board.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import board.vo.UserVo;
import board.mapper.UserMapper;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Map;
@Repository
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public void insertUser(UserVo userVo) throws Exception { // 비밀번호 암호화 후 회원가입 진행
messageDigest(userVo, userVo.getPassword());
userMapper.insertUser(userVo);
}
@Override
public int idCheck(String username) throws Exception { // 중복 아이디 확인
return userMapper.idCheck(username);
}
@Override
public String loginProc(UserVo userVo) throws Exception { // 비밀번호 암호화 후 로그인 진행
messageDigest(userVo, userVo.getPassword());
return userMapper.loginProc(userVo);
}
@Override
public UserVo getUserInfo(String username) { // 회원 정보 조회
return userMapper.getUserInfo(username);
}
}
UserMapper.java
package board.mapper;
import org.apache.ibatis.annotations.Mapper;
import board.vo.UserVo;
@Mapper
public interface UserMapper {
void insertUser(UserVo userVo) throws Exception;
String loginProc(UserVo userVo) throws Exception;
int idCheck(String username) throws Exception;
UserVo getUserInfo(String username);
}
3. user.js 작성
function loginProc() { // 로그인 실행 로직
let username = document.getElementById('username').value.trim();
let password = document.getElementById('password').value.trim();
if (username === "") {
alert("아이디를 입력해주세요.");
document.getElementById('username').focus();
return false;
}
if (password === "") {
alert("비밀번호를 입력해주세요.");
document.getElementById('password').focus();
return false;
}
let data = {
username:username,
password:password
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "/user/loginProc");
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.onload = function() {
if (xhr.status === 200 || xhr.status === 201) {
let resp = xhr.responseText;
let result = JSON.parse(resp);
if (resp.status === 500) {
alert("에러가 발생했습니다.");
} else {
if (username) { // 회원 정보를 반환받은 경우
alert("로그인이 완료되었습니다.");
location.href = "/";
} else { // 반환받은 회원 정보가 없는 경우
alert("아이디 또는 비밀번호를 확인해주세요.");
document.getElementById('username').focus();
}
}
} else {
console.log(xhr.responseText);
alert("에러가 발생했습니다. \n에러 코드: " + xhr.status);
}
};
xhr.onerror = function() {
console.log(xhr.responseText);
alert("에러가 발생했습니다. \n에러 코드: " + xhr.status);
};
xhr.send(JSON.stringify(data));
}
4. loginForm.jsp 작성
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../layout/header.jsp"%>
<title>로그인</title>
<html>
<body>
<c:set var="REST_API_KEY" value="69eddbebb2b07d6a316fc057c32fdbdf"/>
<%--<c:set var="REDIRECT_URI" value="http://localhost/user/kakao"/>--%>
<c:set var="REDIRECT_URI" value="http://staffriends.duckdns.org/user/kakao"/>
<h2 style="text-align: center; margin-top: 30px; margin-bottom: 70px; font-family: KakaoBold;">로그인</h2>
<section style="padding-bottom: 50px;">
<div class="container center-div">
<form method="post" class="container center-div container-size">
<div class="form-group" style="margin-bottom: 32px;">
<h5 style="text-align: left">아이디</h5><input type="text" class="form-control" placeholder="아이디를 입력하세요." name="username" id="username">
</div>
<div class="form-group">
<h5 style="text-align: left">비밀번호</h5><input type="password" class="form-control" placeholder="비밀번호를 입력하세요." name="password" id="password">
</div>
<div style="text-align: center; padding-bottom: 20px;"><a href="javascript:findMyIdPopUp()">아이디 찾기</a> | <a href="javascript:findMyPasswordPopUp()">비밀번호 찾기</a></div>
<input class="btn btn-staffriends btn-lg center-div" type="button" value="로그인" onclick="loginProc()">
<a href="https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code"><img src="/img/kakao_login_medium_wide.png" class="btn-block" style="margin-top: 5px;height: 50px"></a>
</form>
</div>
</section>
</body>
</html>
<%@ include file="../layout/footer.jsp"%>
5. sql-user.xml 작성
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="board.mapper.UserMapper">
<insert id="insertUser" parameterType="board.vo.UserVo">
<![CDATA[
INSERT INTO user
(
name,
username,
password,
email,
nickname,
join_date,
oauth
)
VALUES
(
#{name},
#{username},
#{password},
#{email},
#{nickname},
now(),
#{oauth}
)
]]>
</insert>
<select id="idCheck" parameterType="String" resultType="Integer">
<![CDATA[
SELECT
count(*) as username
FROM
user
WHERE
username = #{username}
]]>
</select>
<select id="loginProc" parameterType="board.vo.UserVo" resultType="String">
<![CDATA[
SELECT
username
FROM
user
WHERE
username = #{username} AND password = #{password}
]]>
</select>
<select id="getUserInfo" parameterType="String" resultType="board.vo.UserVo">
<![CDATA[
SELECT
*
FROM
user
WHERE
username = #{username}
]]>
</select>
</mapper>
프로젝트 전체 코드 Github 주소
https://github.com/sungwoo-jo/Staffriends-Project
728x90
'프로젝트 > Staffriends 프로젝트' 카테고리의 다른 글
[Staffriends 프로젝트] (2) 게시판 CRUD 구현하기 - 1. 글쓰기 (0) | 2023.05.22 |
---|---|
[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 3. 회원 정보 수정 (0) | 2023.05.22 |
[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 1. 회원가입 (0) | 2023.05.22 |