Bean 수동 등록
@Component를 사용하면 @ComponentScan에 의해 자동으로 스캔되어 해당 클래스를 Bean으로 등록해줌@Controller, @Service와 같은 어노테이션을 사용해 Bean으로 등록하고 관리하여 개발 생산성을 유리하게 함@Configuration
public class PasswordConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
@Bean을 설정함@Configuration을 설정함@Bean이 설정된 메서드명public PasswordEncoder passwordEncoder() {..} -> passwordEncoderChicken
package com.sparta.springauth.food;
import org.springframework.stereotype.Component;
@Component
@Primary
public class Chicken implements Food {
@Override
public void eat() {
System.out.println("치킨을 먹습니다.");
}
}
Pizza
package com.sparta.springauth.food;
import org.springframework.stereotype.Component;
@Component
@Qualifier("pizza")
public class Pizza implements Food {
@Override
public void eat() {
System.out.println("피자를 먹습니다.");
}
}
@Qualifier("pizza")를 추가함Food Interface
package com.sparta.springauth.food;
public interface Food {
void eat();
}
test 코드
@SpringBootTest
public class BeanTest {
@Autowired
@Qualifier("pizza")
Food food;
@Test
@DisplayName("Primary 와 Qualifier 우선순위 확인")
void test1() {
// 현재 Chicken 은 Primary 가 적용된 상태
// Pizza는 Qualifier 가 추가된 상태입니다.
food.eat();
}
}
@Autowired Food food; 처럼 사용한다면 food 필드에 Bean을 주입해줘야하는데 같은 타입의 Bean 객체가 하나 이상(chicken, pizza)이기 때문에 어떤 Bean을 등록해줘야할지 몰라 오류가 발생함
@Autowired Food pizza;, @Autowired Food chicken;@Autowired가 기본적으로 Bean Type(Food)로 DI를 지원하며, 연결이 되지 않을 경우 Bean Name(chicken, pizza)으로 찾는다는 것을 알 수 있음같은 타입의 Bean들에 Qualifier와 Primary가 동시에 적용되어있다면 Qualifier의 우선순위가 더 높음
하지만, Qualifier는 적용하기 위해 주입 받고자하는 곳에 해당 Qualifier를 반드시 추가해야함
-> 따라서 같은 타입의 Bean이 여러 개 있을 때는 범용적으로 사용되는 Bean 객체에는 Primary를 설정하고 지엽적으로 사용되는 Bean 객체에는 Qualifier를 사용하는 것이 좋음
인증 (Authentication)
: 해당 유저가 실제 유저인지 인증하는 개념
인가 (Authorization)
: 해당 유저가 특정 리소스에 접근이 가능한지 허가를 확인하는 개념

1. 일반적으로 서버-클라이언트 구조로 되어있고, 실제로 이 두가지 요소는 아주 멀리 떨어져있음
2. Http라는 프로토콜을 이용해여 통신하는데, 그 통신은 비연결성(Connectionless) 무상태(Stateless)로 이루어짐



public static void addCookie(String cookieValue, HttpServletResponse res) {
try {
cookieValue = URLEncoder.encode(cookieValue, "utf-8").replaceAll("\\+", "%20"); // Cookie Value 에는 공백이 불가능해서 encoding 진행
// cookieValue 값에 있는 공백을 없애주는 코드
Cookie cookie = new Cookie(AUTHORIZATION_HEADER, cookieValue); // Name-Value
cookie.setPath("/");
cookie.setMaxAge(30 * 60);
// Response 객체에 Cookie 추가
res.addCookie(cookie);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage());
}
}
new Cookie(AUTHORIZATION_HEADER, cookieValue);: Cookie에 저장될 Name과 Value를 생성자로 받는 Cookie 객체를 생성
setPath("/"), setMaxAge(30 * 60): Path와 만료시간을 지정함
HttpServletResponse 객체에 생성한 Cookie 객체를 추가하여 브라우저로 반환함
Cookie 생성은 범용적으로 사용될 수 있기 때문에 static 메서드로 선언함
쿠키 읽기
@GetMapping("/get-cookie")
public String getCookie(@CookieValue(AUTHORIZATION_HEADER) String value) {
System.out.println("value = " + value);
return "getCookie : " + value;
}
@CookieValue("Cookie의 Name"): Cookie의 Name 정보를 전달해주면 해당 정보를 토대로 Cookie의 Value를 가져옴@GetMapping("/create-session")
public String createSession(HttpServletRequest req) {
// 세션이 존재할 경우 세션 반환, 없을 경우 새로운 세션을 생성한 후 반환
HttpSession session = req.getSession(true);
// 세션에 저장될 정보 Name - Value 를 추가합니다.
session.setAttribute(AUTHORIZATION_HEADER, "Robbie Auth");
return "createSession";
}
req.getSession(true): 세션이 존재할 경우 세션을 반환하고 없을 경우 새로운 세션을 생성함@GetMapping("/get-session")
public String getSession(HttpServletRequest req) {
// 세션이 존재할 경우 세션 반환, 없을 경우 null 반환
HttpSession session = req.getSession(false);
String value = (String) session.getAttribute(AUTHORIZATION_HEADER); // 가져온 세션에 저장된 Value 를 Name 을 사용하여 가져옵니다.
System.out.println("value = " + value);
return "getSession : " + value;
}
req.getSession(false): 세션이 존재할 경우 세션을 반환하고 없을 경우 null을 반환함session.getAttribute("세션에 저장된 정보 Name"): Name을 사용하여 세션에 저장된 Value를 가져옴implementation 'org.springframework.boot:spring-boot-starter-security' 의존성/login 기본 로그인 페이지 제공/login으로 리다이렉트 -> 기본 로그인 페이지 표시됨exclude = SecurityAutoConfiguration.class를 통해서 시큐리티 자동설정의 상태를 끄려고 해도 그 종류가 많기 때문에, 위 코드처럼 하나만 제외해도 나머지는 살아있어서 오류가 발생package com.sparta.springauth.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.formLogin(form -> form.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/api/create-cookie",
"/api/get-cookie",
"/api/create-session",
"/api/get-session"
).permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
위 코드를 통해서 해당 경로로 이동할 때, 기본 로그인 페이지(/login)를 안 뜨게 하고, 쿠키 테스트할 때 방해되는 csrf도 끔