[spring Boot]_13일차_Security

youuu·2022년 11월 3일
0

SPRING

목록 보기
22/33

Spring Security란?

Spring Security는 Spring기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크이다.
Spring Security는 '인증(Authentication)'과 '권한(Authorization)'에 대한 부분을 Filter의 흐름에 따라 처리를 하고 있다.
많은 보안 관련 옵션들을 제공해주어 개발자가 보안 로직을 하나씩 작성하지 않아도 되는 장점이 있다.


🎯 인증(Authorizatoin)과 인가(Authentication)

📌 인증(Authentication) :

사이트에 접속하려는 자가 누구인지 확인하는 절차. (사용자가 본인인지 확인)
UsernamePassword를 통한 인증을 할 수 있다. (Session관리, Token관리)
SNS로그인을 통한 인증 위임을 할 수도 있다.

📌 인가, 권한(Authorization)

사용자가 어떤 일을 할 수 있는지 권한 설정하는 절차이다.
특정 페이지/리소스에 접근할 수 있는지 권한을 판단한다.
Secured, PrePostAuthorize 어노테이션으로 쉽게 권한 체크를 할 수 있다.
비즈니스 로직이 복잡한 경우 AOP를 이용해 권한 체크를 해야한다.


🎯 Spring Security 방법

  • 혼돈: 메시지 원문의 내용을 짐작하기 어렵게 만드는 것을 의미
  • 확산: 암호화 알고리즘의 패턴 추론을 어렵게 만드는 역할
  • 치환(Substitution) : 문자열을 다른 문자열로 이동 및 교체
  • 이동(Transposition) : 원칙에 따라 문자열 순서를 무작위로 바꿔 이동

🎯 암호화 유형

  1. 대칭 암호화 : 발신자와 수신자가 동일한 개인 암호화 키를 사용하여 암호화된 메시지를 디코딩하고 인코딩(DES,SEED,AES,Aria..) , 비밀키

  2. 비대칭 암호화 : 개인정보를 보호하기 위해 대칭 암호화보다는 더 고차원적이고 안전한 방법 공개키는 발신자와 수신자 모두 동일한 키를 가지고 있지만 개인키는 각 당사자가 고유한 키(RSA,Rabin, ELGamal )

  3. 해쉬(Hash) : 임의길이를 해시함수(해시 알고리즘)를 이용하여 고정된 길이의 암호화된 문자열 MD5, SHA-1, HAS-180은 사용하면 안된다. SHA-256, SHA-512등을 사용하기를 권고함.
    참고로 SHA-512가 보안이 더 좋음
    bcrypt : 패스워드를 위해 탄생해서 아주 강력한 해시 알고리즘이 적용됨. ▶ Spring security에서 사용

🎯 Iterable

반복되는것?


Security 설정에서 loginProcessingUrl("/login")
login 요청이 오면 자동으로 UserDetailsService Type으로
IOC되어 있는 loadUserByUsername Method가 실행(약속)
Security session
( 내부-> Authentication (내부->userDetails) )


⭐.configuration 패키지 생성

security 하기위해선 .configuration 를 만들어야한다.



1. 인증X 암호화만 거는 방법


📌📋 SecurityController01.java

package com.oracle.oBootSecurity01.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
public class SecurityController01 {

	@Autowired
	private BCryptPasswordEncoder bCryptPasswordEncoder;
	
	@GetMapping("/user")
	public String user(String passwd) {
		System.out.println("SecurityController01 user START ==========");
		System.out.println("SecurityController01 user passwd ----> " + passwd);
		//										Hash 암호화
		String encPasswd = bCryptPasswordEncoder.encode(passwd);
		System.out.println("SecurityController01 userencPasswd ----> " + encPasswd);
	
		return "user";
	}
	
	@GetMapping("/manager")
	public String manager() {
		System.out.println("SecurityController01 manager START ==========");
		
		return "manager";
	}
	
	@GetMapping("/admin")
	public String admin() {
		System.out.println("SecurityController01 admin START ==========");
		
		return "admin";
	}
}

📋 SecurityController01.java

package com.oracle.oBootSecurity01.controller;

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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;


@Configuration		//IoC 빈(bean)을 등록
@EnableWebSecurity //필터 체인 관리 시작 어노테이션
public class SecurityConfig {

	@Bean 			// 컨트롤러 로직 어디에서든 암호화를 사용할 수 있다.
	public BCryptPasswordEncoder encoderPwd() {
		return new BCryptPasswordEncoder(); 
	}
	
	
	@Bean
	protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.authorizeHttpRequests()	//인가,권한
			.anyRequest()
			.permitAll(); //permitAll : 다 허용
		
		return http.build();
	}
}

💻📋 index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>JungChoong SHOP</h1>
		<p class="lead">회원 기능</p>
		<p>
			<a class="btn btn-lg btn-secondary" href="/user?passwd=123">회원
				가입</a> <a class="btn btn-lg btn-secondary" href="/members">회원 목록</a>
		</p>
		<p class="lead">상품 기능</p>
		<p>
			<a class="btn btn-lg btn-dark" href="/items/new">상품 등록</a> <a
				class="btn btn-lg btn-dark" href="/items">상품 목록</a>
		</p>
		<p class="lead">주문 기능</p>
		<p>
			<a class="btn btn-lg btn-info" href="/order">상품 주문</a> <a
				class="btn btn-lg btn-info" href="/orders">주문 내역</a>
		</p>
	</div>
</body>
</html>

2. 인증, 암호화 방법


중요한 정보를 암호화.

🙄 두번째 방법은 잘 모르겠다. 정리가 안된다. 찾아보고 다시 정리하기


📂 com.oracle.oBootSecurity02.entity

📋 User.java

package com.oracle.oBootSecurity02.entity;

import java.security.Timestamp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import lombok.Data;

@Entity
@SequenceGenerator (name = "user_seq_gen",
					sequenceName = "user_seq_generator",
					initialValue = 1,
					allocationSize = 1)
@Table(name = "user01")
@Data
public class User {
	@Id
	@GeneratedValue (strategy = GenerationType.SEQUENCE,
					 generator = "user_seq_gen")
	private int 		id;
	private String		username;
	private String		password;
	private String		email;
	private String		role;	// ROLE_USER, ROLE_ADMIN, ROLE_MANAGER 
	private Timestamp	createdate;
	
}

📂 com.oracle.oBootSecurity02.repository

📋 SecurityRepository.java

interface

package com.oracle.oBootSecurity02.repository;

import com.oracle.oBootSecurity02.entity.User;

public interface SecurityRepository {
	void save(User user);
	User findByUsername(String username);
	
}

📂 com.oracle.oBootSecurity02.repository

📋 JpaSecurityRepository.java

package com.oracle.oBootSecurity02.repository;

import javax.persistence.EntityManager;

import org.springframework.stereotype.Repository;

import com.oracle.oBootSecurity02.entity.User;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class JpaSecurityRepository implements SecurityRepository {

	private final EntityManager em;
	
	@Override
	public void save(User user) {
		em.persist(user);
		
	}

	@Override
	public User findByUsername(String username) {

		return null;
	}
}

📂 com.oracle.oBootSecurity02.controller

📋 SecurityController02.java

package com.oracle.oBootSecurity02.controller;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import com.oracle.oBootSecurity02.service.SecurityService;
import com.oracle.oBootSecurity02.service.SecurityServiceImpl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
@RequiredArgsConstructor
public class SecurityController02 {
//	private final SecurityServiceImpl securityServiceImpl; 
	private final SecurityService securityService; 
	private final BCryptPasswordEncoder bCryptPasswordEncoder;
	
	@GetMapping("/user")
	public String user(String passwd) {
		System.out.println("SecurityController02 user START ==========");
		System.out.println("SecurityController02 user passwd ----> " + passwd);
		//										Hash 암호화
		String encPasswd = bCryptPasswordEncoder.encode(passwd);
		System.out.println("SecurityController02 userencPasswd ----> " + encPasswd);
	
		return "user";
	}
	
	@GetMapping("/user/2")
	public String user2() {
		System.out.println("SecurityController02 user2 START ==========");
		
		return "user";
	}
	
	@GetMapping("/manager")
	public String manager() {
		System.out.println("SecurityController02 manager START ==========");
		
		return "manager";
	}
	
	@GetMapping("/manager/2")
	public String manager2() {
		System.out.println("SecurityController02 manager2 START ==========");
		
		return "manager";
	}
	
	@GetMapping("/admin")
	public String admin() {
		System.out.println("SecurityController02 admin START ==========");
		
		return "admin";
	}
	
	@GetMapping("/admin/2")
	public String admin2() {
		System.out.println("SecurityController02 admin2 START ==========");
		
		return "admin";
	}
	
}

📂 static

💻📋 index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>JungChoong SHOP</h1>
		<p class="lead">User 권한</p>
		<p>
			<a class="btn btn-lg btn-secondary" href="/user?passwd=123">user
				가입</a> <a class="btn btn-lg btn-secondary" href="/user/2">user2</a>
		</p>
		<p class="lead">Manger 권한</p>
		<p>
			<a class="btn btn-lg btn-dark" href="/manager">manager</a> <a
				class="btn btn-lg btn-dark" href="/manager/2">manager2</a>
		</p>
		<p class="lead">Admin 권한</p>
		<p>
			<a class="btn btn-lg btn-info" href="/admin">admin</a> <a
				class="btn btn-lg btn-info" href="/admin/2">admin2</a>
		</p>
	</div>
</body>
</html>

📂 com.oracle.oBootSecurity02.controller

📋 SecurityController02.java

package com.oracle.oBootSecurity02.configuration;

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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

	@Bean
	public BCryptPasswordEncoder encodePwd() {
		
		return new BCryptPasswordEncoder();
	}
	
	protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.authorizeRequests()
			.antMatchers("/user/**").authenticated();
		return http.build();
	}
	
}

👨‍🏫 예제보고 다시 정리.

참고

profile
공부중인 주니어 개발자

0개의 댓글