728x90
반응형
스프링에서 암호화 설정을 하는 법
설정하기
1단계: pom.xml에 spring security DI 주입
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
2단계: spring-security.xml
<!-- web.xml에 spring-security.xml 파일정보가 구성되어있어야 한다. -->
<!-- bcryptPasswordEncoder 빈객체가 MemberServiceImpl클래스에서 주입되어 사용된다.-->
<bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
3단계: web.xml
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/spring/spring-security.xml
</param-value>
스프링 암호화 설정코드 작성법
1단계: MemberController.java
// spring-security.xml BCryptPasswordEncoder클래스가 bean객체로 생성.
@Inject // 의존성 주입
private BCryptPasswordEncoder crptPassEnc;
/* 회원가입(GET) /member/join */
@RequestMapping(value="join", method=RequestMethod.GET)
public void joinGET() {
}
/* 회원가입(POST) */
@RequestMapping(value="join", method=RequestMethod.POST)
public String joinPOST(MemberVO vo, RedirectAttributes rttr) throws Exception {
// 비밀번호 암호화. "1234" -> 다른 문자로 비번으로 생성
vo.setMem_pw(crptPassEnc.encode(vo.getMem_pw()));
service.join(vo);
rttr.addFlashAttribute("msg", "REGISTER_SUCCESS");
return "redirect:/"; // 루트 주소로 이동. HomeController 에 있음. home.jsp에서 "msg" 키사용
}
1단계: 회원가입 요청 → 비밀번호 암호화 진행 → vo저장 → 회원가입 서비스 순으로 실행한다.
/* 로그인(GET) /member/login <a href="/member/login">로그인</a> */
@RequestMapping(value="login", method=RequestMethod.GET)
public void loginGET() {
// 리턴타입이 void인 경우에는 jsp파일명은 요청주소(/member/login)가 된다.
}
/* 로그인(POST) /member/loginPost */
@RequestMapping(value="loginPost", method=RequestMethod.POST)
public String loginPOST(MemberDTO dto, RedirectAttributes rttr, HttpSession session,
Model model, HttpServletResponse response) throws Exception {
logger.info("=====loginPost() execute...");
MemberDTO memDTO = service.login(dto); // service클래스에서 일반암호와 디비에서 가져온 암호문자열
if(memDTO != null) { // 로그인 성공
logger.info("=====로그인 성공");
// 세션 작업 : 저장소 - 서버의 메모리(현재 연결된 사용자 사용이 가능)
session.setAttribute("user", memDTO); // session.getAttribute("user")
// 쿠키를 사용할 경우. 저장소 : 클라이언트(브라우저).
// <input type="checkbox" name="useCookie" /> Remember me
if(memDTO.isUseCookie()) {
// 쿠키 저장
int amount= 60*60*24*7; // 7일
// System.currentTimeMillis() : 서버의 현재시간을 밀리세컨드 읽어온다.
Date sessionLimit = new Date(System.currentTimeMillis()+(1000*amount));
/* 클라이언트 쿠키 설명 : Cookie클래스 사용*/
// 쿠키는 클라이언트의 컴퓨터에 설정된 시간에 의하여 텍스트파일로 저장이 됨
// 브라우저에서 쿠키를 작업해준 사이트 접속을 할때에 브라우저가 쿠키를 메모리상에서 읽고
// 해당사이트에 쿠키정보가 전송이 이루어진다.
// 브라우저를통하여 사이트에 접속할때에 서버에서 고유한 식별자에 해당하는 값을 쿠키형태로
// 클라이언트에게 보내준다. 세션쿠키ID session.getId()
service.saveCookie(session.getId(), sessionLimit, memDTO.getMem_id());
}
rttr.addFlashAttribute("msg", "LOGIN_SUCCESS");
return "redirect:/"; // 루트 주소로 이동. HomeController 에 있음. home.jsp에서 "msg" 키사용
} else { // 로그인 실패
logger.info("=====로그인 실패");
// RedirectAttributes 클래스 ? 주소이동시 정보를 제공하고자 할때 사용.
// 주소이동시 "msg" 키가 노출이 안됨.
rttr.addFlashAttribute("msg", "LOGIN_FAIL"); //로그인 페이지에서 "msg" 키가 사용됨.
// return "/member/login"; jsp파일명
return "redirect:/member/login"; // 주소이동
}
}
※ 로그인 할 시 입력된 비밀번호와 조회된 비밀번호를 일치시켜야 하기 때문에 비밀번호 조회 실행
2단계: 회원정보수정 / 비밀번호변경 / 회원탈퇴
/*
* 비밀번호 재확인(POST) - 회원 정보 수정을 위함
* 받은 url에 해당하는 jsp를 출력
*
* @Params
* String url: 이동할 jsp페이지 이름
*
* @return
* String : 받은 url에 일치하는 jsp호출
*/
//1) 회원정보 수정 url=modify, 2) 비밀번호 변경 url=changepw, 3) 회원탈퇴 url=delete
@RequestMapping(value="checkPw", method=RequestMethod.POST)
public String checkPwPOST(@RequestParam("url") String url,
@RequestParam("mem_pw") String pw,
HttpSession session, Model model) throws Exception {
logger.info("=====checkPw() execute...");
logger.info("=====url: " + url + ", mem_pw: " + pw);
// 인증된 사용자
MemberDTO dto = (MemberDTO) session.getAttribute("user");
//logger.info("=====세션 저장 값: " + dto.toString());
//스프링 security(보안)기술
if(crptPassEnc.matches(pw, dto.getMem_pw())) {
// 비밀번호가 일치하는 경우, url 확인
if(url.equals("modify")) {
model.addAttribute("vo", service.readUserInfo(dto.getMem_id()));
return "/member/modify";
} else if(url.equals("changePw")) {
return "/member/changePw";
} else if(url.equals("delete")) {
return "/member/delete";
}
}
// 비밀번호가 일치하지 않거나, url이 정해진 url이 아닌 경우
model.addAttribute("url", url);
model.addAttribute("msg", "CHECK_PW_FAIL");
return "/member/checkPw";
}
/*
* 비밀번호 확인 Ajax용
*/
@ResponseBody
@RequestMapping("checkPwAjax")
public ResponseEntity<String> checkPwAjax(@RequestParam("mem_pw") String mem_pw, HttpSession session) {
logger.info("=====checkPwAjax() execute...");
ResponseEntity<String> entity = null;
MemberDTO dto = (MemberDTO) session.getAttribute("user");
logger.info("=====mem_pw: " + mem_pw);
logger.info("=====dto: " + dto.toString());
if(crptPassEnc.matches(mem_pw, dto.getMem_pw())) {
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} else {
entity = new ResponseEntity<String>("FAIL", HttpStatus.OK);
}
return entity;
}
/* 회원 정보 수정(POST) */
@RequestMapping(value="modify", method=RequestMethod.POST)
public String modifyPOST(MemberVO vo, RedirectAttributes rttr, HttpSession session) throws Exception {
MemberDTO dto = new MemberDTO();
dto.setMem_id(vo.getMem_id());
dto.setMem_pw(vo.getMem_pw());
// 비밀번호 암호와 작업
vo.setMem_pw(crptPassEnc.encode(vo.getMem_pw()));
service.modifyUserInfo(vo); // 회원수정
/*
처음 로그인시 세션에 저장됐던 정보를 다른 곳에서 사용이 되어질 경우 (회원수정 등)
정보가 수정이 발생이 되면서 세션정보를 갱신해주어야한다.
세션작업 : 수정중에 변경된 정보를 세션에 새로 반여아는 의미
*/
session.setAttribute("user", service.login(dto));
rttr.addFlashAttribute("msg", "MODIFY_USER_SUCCESS");
return "redirect:/";
}
※ 회원정보 수정은 ajax을 이용하여 cryptPassEnc()요청
/* 비밀번호 변경(POST) */
@RequestMapping(value="changePw", method=RequestMethod.POST)
public String changePWPOST(MemberDTO dto, RedirectAttributes rttr, HttpSession session) throws Exception {
logger.info("=====changePWPOST() execute...");
// 비밀번호 암호화 후 변경
dto.setMem_pw(crptPassEnc.encode(dto.getMem_pw()));
service.changePw(dto);
// 세션의 비밍번호 재설정
MemberDTO memDTO = (MemberDTO) session.getAttribute("user");
memDTO.setMem_pw(dto.getMem_pw());
session.setAttribute("user", memDTO);
rttr.addFlashAttribute("msg", "CHANGE_PW_SUCCESS");
return "redirect:/";
}
/* 회원 탈퇴{POST) */
@RequestMapping(value="delete", method=RequestMethod.POST)
public String deletePOST(String mem_id, HttpSession session, RedirectAttributes rttr) throws Exception {
logger.info("=====deletePOST() execute...");
service.deleteUser(mem_id);
// 회원탈퇴시 세션소멸작업
session.invalidate();
rttr.addFlashAttribute("msg", "DELETE_USER_SUCCESS");
return "redirect:/";
}
3단계 : passBcrypt.jsp 작성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
비밀번호: ${ogi_pass} <br />
암호화된 비밀번호: ${enc_pass} <br />
암호화된 비밀번호2: ${enc_pass2} <br />
</body>
</html>
4단계 : memberMapper.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="com.demo.mappers.MemberMapper">
<!-- MemberVO 가져오기 -->
<select id="readUserInfo" parameterType="string" resultType="MemberVO">
select mem_id, mem_name, mem_pw, mem_email, mem_zipcode, mem_addr, mem_addr_d,
mem_phone, mem_nick, mem_accept_e, mem_point,
mem_date_sub, mem_date_up, mem_date_last, mem_authcode
from member_tbl
where mem_id = #{mem_id}
</select>
<!-- 로그인(MemberDTO 가져옴) 비번을 파라미터 사용안하고 있음에 주의 -->
<select id="login" parameterType="MemberDTO" resultType="MemberDTO">
select mem_id, mem_pw, mem_nick, mem_name, mem_point, mem_date_last
from member_tbl
where mem_id=#{mem_id}
</select>
<!-- 로그인 시간 업데이트 -->
<update id="loginUpdate" parameterType="string">
update member_tbl
set mem_date_last = sysdate
where mem_id = #{mem_id}
</update>
<!-- 회원가입 -->
<insert id="join" parameterType="MemberVO">
insert into member_tbl(mem_id, MEM_NAME, MEM_PW, MEM_EMAIL, MEM_ZIPCODE,
MEM_ADDR, MEM_ADDR_D, MEM_PHONE, MEM_NICK, MEM_ACCEPT_E)
values(#{mem_id}, #{mem_name}, #{mem_pw}, #{mem_email}, #{mem_zipcode},
#{mem_addr}, #{mem_addr_d}, #{mem_phone}, #{mem_nick}, #{mem_accept_e})
</insert>
<!-- 아이디 중복 체크 -->
<select id="checkIdDuplicate" parameterType="string" resultType="int">
select count(*)
from member_tbl
where mem_id = #{mem_id}
</select>
<!-- 회원정보 수정 -->
<update id="modifyUserInfo" parameterType="MemberVO" >
update member_tbl
set mem_name=#{mem_name}, mem_nick=#{mem_nick}, mem_email=#{mem_email},
mem_phone=#{mem_phone}, mem_zipcode=#{mem_zipcode}, mem_addr=#{mem_addr},
mem_addr_d=#{mem_addr_d}, mem_accept_e=#{mem_accept_e}, mem_date_up=sysdate
where mem_id=#{mem_id}
</update>
<!-- 비밀번호 변경 -->
<update id="changePw" parameterType="MemberDTO">
update member_tbl
set mem_pw = #{mem_pw}
where mem_id=#{mem_id}
</update>
<!-- 회원 탈퇴 -->
<delete id="deleteUser" parameterType="string">
delete from member_tbl
where mem_id=#{mem_id}
</delete>
<!-- 로그인 정보 쿠키 저장-->
<update id="saveCookie" parameterType="Map">
update member_tbl
set mem_session_key = #{mem_session_key},
mem_session_limit = #{mem_session_limit}
where mem_id=#{mem_id}
</update>
<!-- 쿠키에 저장된 세션값으로 로그인 정보 가져옴 -->
<select id="checkUserSession" parameterType="string" resultType="MemberVO">
select *
from tbl_user
where mem_session_key = #{value} and mem_session_limit > now()
</select>
</mapper>
※ 조건에 있는 비밀번호는 주석처리
홈페이지 구축할 시에는 운영측 관점에서
1. 사용자 모드 / 2. 관리자 모드
1. 사용자 모드에서 주요 기능 :
- 회원기능 : MemberController.java
2. 관리자 모드에서 주요 기능 :
- 로그인 : AdminController.java
- 카테고리 : DB에서 데이터를 직접구성
- 상품관리
반응형
'Backend' 카테고리의 다른 글
[Nest.js] Nest.js란 무엇인가 (번역) (0) | 2022.03.27 |
---|