[TIL][Spring] spring-security 기존 로그인/로그아웃 재커스터마이징하기

😂 기존에 있던 ajax 방식의 로그인을 살려서 해보려고 했는데,,,,
아무래도 시간이 좀 걸릴 것 같아 그냥 security 방식에 따르기로 했다........8ㅁ8
일단 스프링 시큐리티를 접목해서 구현하는데에 의의가 있으니, 작은 것에 연연하지 않기로...!
참고 : https://to-dy.tistory.com/81?category=720806

1. 로그인

에러 발생

기존에 있던 main 코드

@RequestMapping(value = "/main", method = { RequestMethod.GET, RequestMethod.POST })
	public String main(HttpServletRequest req, Model model) {
		try {
			// 로그인 후 메인화면
			HttpSession session = req.getSession();
			String userId = session.getAttribute("id").toString();

			if (session != null) {
				// 비로그인 상태
				if (userId == null) {
					session.setAttribute("status", "null");
				} else {
					session.setAttribute("status", "success");
					List<UsersVO> list = userService.getUserInfo(userId);
					for (UsersVO vo : list) {
						// sidebar에 들어가는 정보
						session.setAttribute("userIdx", vo.getIdx());
						session.setAttribute("nickname", vo.getNickname());
						session.setAttribute("level", vo.getLevel());
						break;
					}
				}
			}
		} catch (Exception e) {
			return "signIn";
		}
		//중략
		return "main";
	}

로그인을 하면 link는 main으로 넘어가는데 화면이 넘어가지 않는 오류가 발생해서 main.jsp에 alert를 찍어서 확인했는데 아예 넘어오지 않는 것을 확인 할 수 있었고 NullPointerException이 나는 것을 확인 할 수 있었다.
결국 session에 저장한 id값이 없는게 문제가 된 것이다.
생각해보니 ajax로 로그인하는 코드에서 session에 id를 저장해주었는데, 이제는 이 코드를 사용하지 않기 때문에.....ㅎㅎㅎ

@PostMapping("/signIn/login")
	public Map<String, String> loginCheck(@RequestBody Map<String, Object> user, HttpSession session) {
		/* 로그인 정보를 받아 check 후 로그인 여부 전달
		 * param : ajax로 넘어온 id,pw 정보(json)
		 * return : 결과값을 map에 담아 return
		 * */
		// 로그인 정보를 확인해 message값을 받아옴
		String message = userService.loginCheckMsg(user);
		session.setAttribute("id", user.get("id"));

		Map<String, String> result = new HashMap<String, String>();
		result.put("message", message);

		return result;
	}

해결하기

기존에 session으로 처리한 것을 Authentication으로 처리하도록 변경한다.

@RequestMapping(value = "/main", method = { RequestMethod.GET, RequestMethod.POST })
	public String main(HttpServletRequest req, Model model) {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		Object principal = auth.getPrincipal();

		try {
			if (principal != null) {
				// 로그인 후 메인화면
				HttpSession session = req.getSession();
				String userId = auth.getName();
				// 비로그인 상태
				if (userId == null) {
					session.setAttribute("status", "null");
				} else {
					session.setAttribute("status", "success");
					List<UsersVO> list = userService.getUserInfo(userId);
					for (UsersVO vo : list) {
						// sidebar에 들어가는 정보
						session.setAttribute("userIdx", vo.getIdx());
						session.setAttribute("nickname", vo.getNickname());
						session.setAttribute("level", vo.getLevel());
						break;
					}
				}
			}
            
            //중략. 이하 동일

내가 원하던 화면을 다시 확인할 수 있다!

2. 로그아웃

에러 발생

원래 로그아웃을 누르면 session.invalidate()를 통해서 session out을 하도록 구현했지만 로그인을 할 때 session에 사용자 정보를 담지 않기 때문에 session out을 해도 로그아웃이 실행되지 않는 것을 확인 했다.
security에 logout 기능이 있기 때문에 그것을 활용해야겠다.

기존 코드

<c:choose>
  <c:when test="${status eq 'success' or status eq 'admin'}">
    <a href="${pageContext.request.contextPath }/" class="nav__link">
    	<span class="nav_name">Log Out</span>
    </a>
  </c:when>
  <c:otherwise>
    <a href="${pageContext.request.contextPath }/signIn" class="nav__link">
    	<span class="nav_name">Log In</span>
    </a>
    <a href="${pageContext.request.contextPath }/signUp" class="nav__link">
    	<span class="nav_name">Sign Up</span>
    </a>
  </c:otherwise>
</c:choose>

c 태그를 활용해 로그인이 되어있지 않는 상태에는 login과 signup 버튼이 보이도록 하고, 로그인이 되어 있는 상태에는 logout버튼이 보이도록 구현했다.

변경한 코드

security-context

<logout logout-url="/logout"
	    logout-success-url="/" />

index.jsp(로그아웃 버튼)

<sec:authorize access="isAuthenticated()">
  <form id="logoutForm" action="/logout" method="post">
    <a href="#" onclick="document.getElementById('logoutForm').submit();" class="nav__link">
    	<span class="nav_name">Log Out</span>
    	<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }" >
    </a>
  </form>
</sec:authorize>
<sec:authorize access="isAnonymous()">
  <a href="${pageContext.request.contextPath }/signIn" class="nav__link">
    <span class="nav_name">Log In</span>
  </a>
  <a href="${pageContext.request.contextPath }/signUp" class="nav__link">
  	<span class="nav_name">Sign Up</span>
  </a>
</sec:authorize>

로그아웃 버튼은 꼭 post형식으로 넘겨야하기 때문에 form 태그로 넣어야하지만 css때문에 a태그를 써야만 했다.
그래서 a태그에 onclick을 추가했다.
참고한 블로그에 자세히 나와있음
그리고 테스트 결과 로그아웃이 잘 실행되는 것을 확인했다.


조금 우당탕탕이긴 하지만,,,,차근차근 하나씩 해나가는 기쁨이 크다.
후,,,,이제 관리자로 로그인 하는 것도 설정해봐야지...!

좋은 웹페이지 즐겨찾기