1. Spring Security를 사용하기에 먼저 pom.xml 설정을 해준다.(스프링 시큐리티)
<!-- 스프링 시큐리티 -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
2. 보안 관련이라 컨테이너 관리 파일을 따로 만들어 사용했다.
기존의 servlet-context이 있는 폴더에(src/main/webapp/WEB_INF/spring/appServlet)
spring-security.xml을 생성 후, 아래 코드를 추가한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
</beans:beans>
* 여기서 `<beans>`는 스프링 프레임워크의 설정 파일에서 사용되는 태그로서, 스프링 빈(Bean)을 정의하고 설정하는 역할. 빈<bean>은 스프링 컨테이너에 의해 생성되고 관리되는 객체를 말하며, 이러한 빈을 `<bean>` 태그를 사용하여 정의. `` 태그의 네임스페이스 선언은 스프링 프레임워크의 XML 설정 파일에서 사용할 수 있는 태그들과 스키마를 지정하는 역할. 네임스페이스를 선언하면 해당 스키마에 정의된 태그들을 사용할 수 있게 됨.
* 쉽게말해, 해당 프로젝트의 설정 관리xml을 하나 더 추가한다는 의미.
3. 그러면 이제 웹에서 시큐리티.xml파일을 읽을 수 있도록 web.xml파일로 가서
아래 코드 추가(기존에 아래 spring-security관련 구문만 추가하면 된다.)
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/servlet-context.xml
<!-- 스프링 시큐리티 xml파일 읽을 수 있게 -->
/WEB-INF/spring/appServlet/spring-security.xml
</param-value>
</init-param>
4. 그 다음부터는 이 시큐리티의 암호화 기능을 사용하는 것 뿐이다.
UserController파일에서 입력받은 값과 데이터베이스에 저장하는 데이터 간에 암호화 로직을 설정한다.
먼저 객체부터 생성.
@Autowired
private BCryptPasswordEncoder pwdEncoder;
// 스프링 시큐리티 암호화 기능 사용.
그리고 다시 생각해봐야 할 것은, 회원가입 시 비밀번호를 새로 암호화 시키는 로직으로 수정해야 한다.(post)
@PostMapping("/account/join")
public String joinProcess(UserVO userVo) {
// 회원가입 처리 코드
String inputPass = userVo.getPwd();
String pwd = pwdEncoder.encode(inputPass);
userVo.setPwd(pwd);
try {
userService.join(userVo);
} catch (Exception e) {
// 예외 처리 로직 추가
e.printStackTrace();
// 실패 시 에러 페이지 또는 회원가입 실패 페이지로 이동하도록 처리
return "error-page";
}
// 회원가입 성공 시 홈으로 리다이렉트
return "redirect:/";
}
*위에 pwd 관련 로직이 추가 되었는데; 입력값을 암호화 시켜 저장시키는 로직이다.
* pwdEncoder.encode(입력값)
그와 함께, 로그인 비밀번호 매치도 바뀌고, (post)
@PostMapping("/account/login")
public String login(UserVO vo, HttpServletRequest req, RedirectAttributes rttr) throws Exception{
HttpSession session = req.getSession();
UserVO login = userService.login(vo);
if (login == null || !pwdEncoder.matches(vo.getPwd(), login.getPwd())) {
rttr.addFlashAttribute("msg", "아이디와 비밀번호를 확인해주세요.");
return "redirect:/account/login"; // 리다이렉트하여 로그인 페이지로 돌아감
}else {
session.setAttribute("member", login);
}
// member라는 이름으로 login 객체를 저장함.
return "redirect:/";
}
*pwdEncoder.matches(입력값, 해시화된 암호) 를 비교하여 boolean값으로 낸다.
회원정보 수정 시 비밀번호 암호화 방식도 바뀌고,(post)
@PostMapping("/account/update")
public String postUpdate(UserVO vo) throws Exception{
String inputPass = vo.getPwd();
String pwd = pwdEncoder.encode(inputPass);
vo.setPwd(pwd);
userService.memberUpdate(vo);
return "redirect:/";
}
회원탈퇴 시, 비밀번호 확인 로직도 바뀔 것이다.(post)
// 회원 탈퇴 post
@PostMapping("/account/delete")
public String postDelete(UserVO vo, HttpSession session, RedirectAttributes rttr) throws Exception{
UserVO member = (UserVO)session.getAttribute("member");
// 세션에서 데이터를 가져오려는 건데, 세션 데이터는 기본적으로 Object형이다.
// 그래서 (UserVO)타입으로 형변환 해서 member에 담고 있다.
// 현재 로그인 되어 세션에있는 비밀번호 UserVO 게터 사용.
String sessionPass = member.getPwd();
// vo로 들어오는 비밀번호
String voPass = vo.getPwd();
if(!pwdEncoder.matches(voPass, sessionPass)) {
rttr.addFlashAttribute("msg", false);
// msg라는 이름으로 false를 넘겨준다.
return "redirect:/account/delete";
}
userService.memberDelete(vo);
session.invalidate();
return "redirect:/";
}
5. 여기서 로직이 꼬일 수 있는데;
*pwdEncoder.matches(입력값, 해시화된 암호)는 단순 입력값과 해시화된 암호를 비교하는 거다.
이는 로그인/ 탈퇴 시 비밀번호를 DB의 데이터와 비교 할 때,입력값은 그대로 두고,
아이디 일치정보를 우선 셀렉트 하여, 그 레코드의 암호와 비교해야 한다.
결론은, 데이터와 일치 확인하는 쿼리문을 수정할 필요가 있다.
일단, 아이디 일치하면 그 다음 암호를 꺼내서 비교해야 할테니.
accountMapper.xml파일에서 아래 코드를 수정한다.(비밀번호를 바로 검증했던 로직을 주석 처리.)
<!-- 로그인 -->
<select id="login" resultType="com.project.model.UserVO">
SELECT *
FROM user
WHERE id = #{id}
<!-- AND pwd = #{pwd} -->
</select>
<!-- 회원탈퇴 -->
<delete id="memberDelete">
DELETE FROM user
WHERE id = #{id}
<!-- AND pwd = #{pwd} -->
</delete>
확인. 나이스.
'Programming > 스프링(spring) - Enterprise' 카테고리의 다른 글
스프링(spring)/ +더하기 2(데이터베이스 상호작용, 주제별 게시판 만들기) (0) | 2023.08.04 |
---|---|
스프링(spring)/ +더하기 1(검색 시스템과 알림 시스템) (0) | 2023.08.02 |
스프링(spring)/ 회원 시스템 구축 3(회원정보 수정 및 탈퇴) (0) | 2023.08.01 |
스프링(spring)/ 회원 시스템 구축 2(로그인 페이지) (0) | 2023.08.01 |
스프링(spring)/ 회원 시스템 구축 1(회원가입 페이지) (0) | 2023.08.01 |