Web & Server/Spring & Spring Boot

Spring Boot - (9) Property, Authentication Principal

Simplify - Jonghun 2018. 10. 10. 13:11

다음으로는, 설정 파일을 읽고, 현재 요청에 대한 사용자 정보를 조회하는 방법을 알아보도록 하겠습니다. API를 호출할 때, 내 정보를 같이 넘기게 해서, 이를 통해 사용자에 대한 상세 정보를 알 수는 있겠으나, 이렇게 하면 Client 쪽에서의 위변조를 통해 요청하는 사용자를 다른 사람으로 바꿔치기 할 가능성이 있습니다. (보안적으로도 해결이 가능한 부분이긴 합니다)


그렇지만, 이렇게 매번 Call 마다 사용자 정보를 포함하게 하는 것은 사용성 측면에서 매우 비효율적이고, 관리 주체가 서버가 되지 않고 Client 에서 준 정보를 무조건 믿어야 하는 점을 보면 제대로 된 방법은 아닙니다. 결과적으로는 현재 서버가 내어 준 Session 정보를 토대로 하여 사용자 정보가 무엇인지를 가져오는 것이 더욱 좋은 방법이라고 할 수 있습니다. 


여기서는 이러한 사용자 정보를 어떻게 관리하는지 부분에 대해 알아보고, 설정 파일(application.properties, appication.yml 등)을 통해서 알아낸 정보들을 꺼내어 쓰고자 할 떄 어떻게 꺼내는지 알아봅니다.



Controller 구현하기


이번 작업에서는 아래와 같이 Controller 를 만들어 두고 설명을 시작하겠습니다. 우선 아래와 같은 Controller 를 하나 만들어둡니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.simplify.sample.property.controller;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.simplify.sample.security.domain.SecurityMember;
 
@Controller
public class PropertyController {
 
    private Logger LOGGER = LoggerFactory.getLogger(PropertyController.class);
    
    @Value("${logging.path}")
    private String logging_path;
    
    @RequestMapping("/openapi/getProperty")
    public @ResponseBody String getProperty(@AuthenticationPrincipal SecurityMember securityMember) {
        
        StringBuffer sb = new StringBuffer();
        
        if(securityMember != null) {
            sb.append("securityMember.getIp()=")
                .append(securityMember.getIp())
                .append(" / ");
        }else {
            sb.append("securityMember is null / ");
        }
        sb.append("logging_path=")
            .append(logging_path);
        
        LOGGER.debug(sb.toString());
        
        return sb.toString();
        
    }
    
    @RequestMapping("/getMember")
    public @ResponseBody String getMember(@AuthenticationPrincipal SecurityMember securityMember) {
        
        StringBuffer sb = new StringBuffer();
        
        if(securityMember != null) {
            sb.append("securityMember.getIp()=")
            .append(securityMember.getIp());
        }
        
        LOGGER.debug(sb.toString());
        
        return sb.toString();
        
    }
    
}
 
cs


/openapi/getProperty


  • @ResponseBody 로 String 형태로 답을 줍니다. 즉 화면 이동이 있지 않고(jsp, ModelAndView, 등) API호출인 것 처럼 그대로 문자열을 response 해 주는 것입니다. 
      
  • /openapi/** 로 시작하였으므로, 앞서 SecurityConfig 에서 정의해 둔 것 처럼 인증 처리를 거치지 않고 API 호출이 가능합니다. 
      
  • function 에 들어오는 parameter 중 앞서 SecurityConfig 에서 User 상속받았던 객체를 @AuthenticationPrincipal annotaion을 붙여 넣어줍니다. 이렇게 되면 저 정보는 Spring 에서 자동으로 autowired 되어 들어오게 됩니다.
      
  • 앞에서는 SecurityMember 가 있는지 확인하고 있으면 그 ip 정보를 문자열에 넣어줍니다. 또한 application.yml 에 선언된 값 중에서 logging.path 정보를 가져와 return 할 문자열에 포함시킵니다. 

1
2
3
logging:
  path: c:/dev/log/spring
  file: log-file  
cs


결과적으로, 사용자 정보를 가져오지는 못합니다. 이유는, openapi 로 시작한 것은 인증을 하지 않는 것으로 정의했고, 그렇게 되면 인증된 사용자 정보 역시 넣어주지 않기 때문입니다. 




/getMember


  • 앞선 /openapi/getProperty 와 유사하게 동작하지만, URI 가 /openapi/** 로 시작하지 않습니다. 
/getMember 를 호출하게 되면, 로그인 화면으로 이동하고 로그인을 완료하면 사용자 정보가 올바르게 나타납니다.