로그아웃

  • nav에서 @{/logout} method="post" 방식으로 form태그로 감싸고 submit 버튼 하나 만들고
  • WebSecurityConfig logout 람다식 오른쪽에 .logoutUrl("/logout") 붙여준다.
  • 2가지 규칙을 반드시 지켜야 정상 동작
    - url : /logout
    - method : post

시큐리티 컨텍스트(1)

  • 사용자의 현 상황을 알기 위해 SecurityContext를 쓴다.
    (= 현재 상황을 보여주는 thymeleaf다~ 라고 생각하면 된다?)
  • 현재 로그인한 사용자의 인증 정보를 저장 및 유지
  • 현재 로그인한 사용자의 인증 정보를 저장하는 곳

시큐리티 컨텍스트(2)

1) 속성

설명 예제
sec:authentication="표현식" 현재 인증된 사용자 정보 표시 <span sec:authentication="name"></span>
sec:authorize="표현식" 특정 조건(권한)을 만족하는 경우만 해당 HTML 요소 렌더링 <div sec:authorize="isAuthenticated()">
로그인된 사용자만 보임
</div>

2) sec:authorize 표현식
표현식 설명
hasRole('권한명') 해당 권한을 가진 유저만 접근 가능
hasAnyRole('권한1', '권한2') 작성된 권한 중 하나를 가진 유저만 접근 가능
permitAll() 모든 유저 접근 가능
denyAll() 모든 유저의 접근 제한
isAnonymous() 인증하지 않은 유저만 접근 가능
isRememberMe() 자동 로그인 기능을 사용한 유저만 접근 가능
isAuthenticated() 인증한 유저만 접근 가능
isFullyAuthenticated() 인증을 하고, 자동 로그인 기능을 사용하지 않은 유저만 접근 가능
  • sec:authorize 표현식
  • hasRole('권한명') 해당 권한을 가진 유저만
  • hasAnyRole('권한1','권한2') 작성된 권한 중 하나를 가진 유저만 접근 가능
  • permitAll()
  • denyAll() 모든 유저의 접근 제한 - 개발자만 보고 싶은 경우
  • isAnonymous() 인증하지 않은 유저만 접근
  • isRememberMe() 자동 로그인 기능을 사용한 유저만 접근 가능
  • isAuthenticated() 인증한 유저만 접근 가능
  • isFullyAuthenticated() 인증을 하고, 자동 로그인 기능을 사용하지 않은 유저만 접근 가능

3)추가설명

  • 시큐리티 컨텍스트는 sec 네임스페이스를 쓴다.
  • 시큐리티 컨텍스트 사용을 위해 html에 속성 추가
<html xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
  • sec:authentication 표현식
  • MemberDetails = UserDetails = principal
  • principal.userName 이런식으로 이름에 접근 가능

remember-me

  • Remember-Me를 설정하면 쿠키를 통해 로그인 상태 유지 가능
    실행시킨 브라우저를 전부 다 끄면 로그인이 풀림(세션 종료)
  • Remember-Me를 설정하면 쿠키를 통해 로그인 상태 유지 가능
    2가지 방식으로 동작
  1. 단순 토큰 방식
  • Remember-Me 쿠키에 username+만료시간+서명(시그니처) 저장
  • 쿠키가 탈취되면 무제한 로그인 가능 -> 보안 취약
  1. 영속성 토큰 방식
  • 쿠키에 serires(토큰 식별자) + token
  • 로그인할 때마다 새로운 토큰을 생성하여 쿠키와 DB를 갱신
  • rememberMeParameter(인풋name값)
  • tokenValiditySeconds(초 단위)
  • alwaysRemember(항상! 기억한다~ true/false)
  • tokenRepository(tokenRepository() <- 이거이거 final로 설정한 거 + 메소드)
  • DB에도 쿠키에도 토큰 정보 일부 저장해서 DB 정보 기준으로 쿠키랑 비교해서 진행한다.
  • remember me 설정 완료

회원 정보 수정

  • 회원 정보를 수정하는 경우에는 2가지 사항을 고려해야함
    • Remember-Me 정보를 무효화해야함
    • 변경된 회원 정보가 Spring Security에 즉시 반영

1) MemberController - remember-me 쿠키 무효화

			// 쿠키(remember-me) 무효화
			Cookie rememberMe = new Cookie("remember-me", null);
			rememberMe.setMaxAge(0); // 쿠키 수명 0초 만들기
			rememberMe.setPath("/"); // 모든 경로의 쿠키 삭제
			response.addCookie(rememberMe); // 브라우저의 쿠키 정보 무효화

2) MemberService - remember-me DB 삭제

	public int updateMember(MemberDto param) {
		int result = 0;
		try {
			// (1) 데이터베이스 회원 정보 수정
			param.setMember_pw(passwordEncoder.encode(param.getMember_pw()));
			Member updated = repository.save(param.toEntity());
			if(updated != null) {
				// (2) remember-me(DB, cookie 두 곳에 있다.)가 있다면 무효화
				// DB는 서비스에서! cookie는 컨트롤러에서! 하자
				// Springboot가 JdbcTemplate 방식을 쓰기 때문에 방식을 존중하는 것
				JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
				String sql = "DELETE FROM persistent_logins WHERE username = ?";
				jdbcTemplate.update(sql, param.getMember_id());
				// (3) 변경된 회원 정보 Security Context에 즉시 반영
				UserDetails updatedUserDetails = userDetailsService.loadUserByUsername(param.getMember_id());
				Authentication newAuth = new UsernamePasswordAuthenticationToken(
						updatedUserDetails, updatedUserDetails.getPassword(), updatedUserDetails.getAuthorities());
				SecurityContextHolder.getContext().setAuthentication(newAuth);
				result = 1;
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

회원 탈퇴

해당 코드 변경된 회원정보를 null로 Security Context에 반영

SecurityContextHolder.getContext().setAuthentication(null);
profile
함께 공부해요!

0개의 댓글