본문 바로가기

Server Programming/Spring Boot Full-Stack Programming

[스프링 풀스택 클론 코딩 - 회원가입] (1-16) 현재 인증된 사용자 정보 참조

반응형

이메일 인증을 하지 않은 사용자에게 메시지

<!-- 로그인하지 않은 사용자에 대한 메시지, 계정정보를 넘겨줘야한다.-->
	<div class="alert alert-warning" role="alert" th:if="${account != null &&!account.emailVerified}">
		데모 가입을 완료하려면 <a href="#" th:href="@{/check-email}" class="alert-link">계정 인증 이메일을 확인</a>하세요.
	</div>

 

 


MainController

package com.demo.main;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.demo.account.CurrentUser;
import com.demo.domain.Account;

@Controller
//첫 페이지로 가는 요청 핸들러 작성

public class MainController {

	//스프링이 제공하는 @AuthenticationPrincipal를 동적으로 사용하기 위해
	//익명일 경우 null로 익명이 아닐 경우 account 객체로 사용
	
	@GetMapping("/")
	public String home(@CurrentUser Account account, Model model) {
		//인증한 사용자인 경우
		if(account !=null) {
			model.addAttribute(account);
		}
		return "index";
		//login 메서드에는 account라는 프로퍼티가 없기 때문에 중간 매개자 UserAccount 작성
		//도메인의 유저정보와 스프링 시큐리티 유저정보의 연결고리
	}
	
	
}

CurrentUser

package com.demo.account;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.security.core.annotation.AuthenticationPrincipal;

//런타임 유지를 위한 어노테이션
@Retention(RetentionPolicy.RUNTIME)
//파라미터에서 쓸수있도록 하는 어노테이션
@Target(ElementType.PARAMETER)
//인증된 사용자인지 판별하는 어노테이션
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account")

//참조가능하도록 인터페이스로 설정
public @interface CurrentUser {

}

 

UserAccount

package com.demo.account;

import java.util.List;

import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;

import com.demo.domain.Account;

import lombok.Getter;

//getter 자동생성 어노테이션
@Getter
//User 인터페이스에서 상속
public class UserAccount extends User {

	//도메인 유저정보
	private Account account;
	
	//스프링 시큐리티 유저정보와 도메인 유저정보 연동
	
	public UserAccount(Account account) {
		super(account.getNickname(), account.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_USER")));
		// 닉네임, 비밀번호, 권한
		this.account=account;
		//account에 설정
	}  
 
}

 

기존 AccountService의 login 메서드

	public void login(Account account) {
		// TODO Auto-generated method stub
		
		//스프링 시큐리티에서 컨텍스트 홀더라는 기능을 이용해 간편하게 로그인
		//토큰을 이용해 로그인 -> 토큰은, 닉네임, 패스워드, 권한으로 이루어져 있다.
		UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(
				account.getNickname(), 
				//nickname이 Principal로 인증된 사용자 여부를 가리는 매개체가 된다.
				account.getPassword(), 
				List.of(new SimpleGrantedAuthority("ROLE USER"))); 
		//권한 목록을 받아서 ROLE USER로 설정
		
//		SecurityContext context =SecurityContextHolder.getContext();
//		context.setAuthentication(token);
		SecurityContextHolder.getContext().setAuthentication(token);
		//해당 토큰을 인증에 사용 ->정석적으로는 form인증할때 username, password를 이용해 AuthenticationManger를 통해 인증
		
//		//정석적인 코드 -> 실제 비밀번호를 접근해야 하므로 사용하기 어렵다.
//		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
//		Authentication authentication = authenticationManager.authenticate(token);
//		SecurityContext context = SecurityContextHolder.getContext();
//		context.setAuthentication(authentication);
	}

 

 

 

변경한 AccountService의 login 메서드

public void login(Account account) {
		// TODO Auto-generated method stub
		
		//스프링 시큐리티에서 컨텍스트 홀더라는 기능을 이용해 간편하게 로그인
		//토큰을 이용해 로그인 -> 토큰은, 닉네임, 패스워드, 권한으로 이루어져 있다.
		UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(
				new UserAccount(account),
				//principal 객체로 변환
				account.getPassword(), 
				List.of(new SimpleGrantedAuthority("ROLE USER"))); 
		//권한 목록을 받아서 ROLE USER로 설정
		
//		SecurityContext context =SecurityContextHolder.getContext();
//		context.setAuthentication(token);
		SecurityContextHolder.getContext().setAuthentication(token);
		//해당 토큰을 인증에 사용 ->정석적으로는 form인증할때 username, password를 이용해 AuthenticationManger를 통해 인증
		
//		//정석적인 코드 -> 실제 비밀번호를 접근해야 하므로 사용하기 어렵다.
//		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
//		Authentication authentication = authenticationManager.authenticate(token);
//		SecurityContext context = SecurityContextHolder.getContext();
//		context.setAuthentication(authentication);
	}
반응형