본문 바로가기

Spring Boot

Spring Boot - Security

https://github.com/Moonseonhyeon/spring-boot-security

 

새 프로젝트 만들기

 

 

아래와 같은 컨트롤러 만들고 나서 실행하면

 

 

 

톰켓이 데이터베이스를 메모리에 띄우기 때문에

 

지금 실행하면 디비없어서 아래와 같이 오류.

 

 

그래서 디비 설정해보자!

 

application. 파일 확장자를 yml로 수정!

 

무조건 자동완성! (띄어쓰기 주의해야하니까)

 

더보기
server:
  port: 8080
  servlet:
    context-path:  /
    encoding:
      charset:  UTF-8
      enabled: true
      force: true
      
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?serverTimezone=Asia/Seoul
    username: cos
    password: cos1234

 

혹시 안 될 경우를 대비해서 forc: true

데이터베이스명?시간설정

 

이렇게 이 파일 저장한 후에

MySQL workbench에 디비, 사용자만들기! 아이디 비밀번호도 설정에 맞춰서!

create user 'cos'@'%' identified by 'cos1234';
GRANT ALL PRIVILEGES ON *.* TO 'cos'@'%';
create database security;
use security;

 

디비까지 만들고 실핼해보면 아래와 같은 로그인 화면이 나타난다.

스프링컨테이너 내부 인터셉터 타이밍에서 security가 나타나서 잠근거다.

 

security - 라이브러리를 넘어서 프레임워크정도이다.

여러가지 권한인증등등 각종 공격들을 다 막아준다.

일이적고 안전하니가 공부해서 쓰자!

다 잠겨있으니까 내가 필요한 거를 푸는 방법을 배울거다

 

 

아이디가 기본으로 user가 제공된다.

비번은 아래와 같이 실행해보면 제공해 준다.

 

로그인하면 아래와 같이 나온다.

 

 

 

세션

 

security-context -> key

Authentication -> value (세션정보)

 

기본정보가 더 다 필요함. 그 필드가 다 정해져 있다. UserDetails에.

기본정보는 username, password이다 -> User 

나머지 더 필요한 정보들은 -> UserDetails

Authentication(value) 안에 User, UserDetails가 있다.

 

Authentication Manager의 도움을 받아야지 Authentication을 만들 수 있다.

이때 Authentication 타입을 만들기 위해서 필요한 인자들이 있다.

User객체에 상식적으로 사용자로부터 받은 username, password가 필요함. 

UserDetails 객체를 만드는데 필요한 필드명들이 있음. 

하지만 회사마다 다 다른 유저를 클래스들의 필드들이 있을 텐데 UserDetails에 컴포지션해서 만든다. 회사에서 필요한 클래스랑 Authentication Manager에 던지면 세션에 key Security-Context의 value로 Athentication객체를 만들어 User, UserDetails를 담아진다.

 

 

 

 

 

 

비밀번호 해쉬로 접근해야만 하도록 되어 있다.

 

그리고 

 

회원가입 페이지라던가 하는 로그인 인증없이도 들어갈 수 있도록 설정하기 위한 파일을 만든다.

 

config 패키지 만들고 안에 SecurityConfig파일

SecurityConfig이 WebSecurityConfigurerAdapter타입이어야지 시큐리티 필터를 관리 할 수 있다. 

 

@EnableWebSecurity

시큐리티 필터 체인 안에 항목들을 관리 시작 어노테이션

 

security filter chain이라는 것이 있다. 여러가지 필터 항목들이 있다.

security filter chain(여러가지가 있는데 어떤 클래스를 쓸지 그때 그때 찾아서 사용하면 된다.) 재정의 해보면 된다.

 

 

@EnableGlobalMethodSecurity(prePostEnabled = true)

 //특정 주소 접근시 권한 및 인증을 미리 체크

내가 만든 컨트롤러 전에 낚아채서 관리한다는 것

 

아래는 공식 문서 . 어노테이션들 궁금하면 공부할 수 있다.

 

https://spring.io/projects/spring-security

 

Spring Security

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

spring.io

https://spring.io/guides/gs/securiing-web/

 

 

 

extends 했으니까 아래와 같이 오버라이드하기

"/" 만 허락

 

 

 

 

negative방식. 다잠그고 내가 antMatchers("/")에 적은거만 열기.

 

 

 

 

 

 

positive방식. 내가 antMatchers("/user/**, ") 설정한거 빼고 다 허락해주기. 다 열고 잠글거만 적기.

 

 

 

 

권한 필요한 요청들은 아래와 같이 login페이지로 이동하고 

 

 

 

 

나머지 요청들은 허락된다.


 

mustache tamplates 사용하기 위해 아래 pox.xml파일에 적습니다.

 

<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-mustache</artifactId>
</dependency>

 

 

login은 예외로 ajax통신 하지말기! 응답시 꼬임..

그럼 form태그로 로그인

 

 

요청을 내 컨트롤러 타게 하지 않고 Authentication Manager를 타게 해줘야한다.

 

//요청을 시큐리티가 낚아채서 Authentication Manager로 타게 하는 설정이다. 그러면 

 

 

기본적으로 스프링은 form태그요청시에만 csrf-token을 들고 post요청을 해야만 허가해준다.

 

시큐리티가 다른 쪽에서 임의로 <form 만들어서 요청하는걸 막는거다. 

csrf-token은 스프링서버가 만들어주는거다.

 

<form>

<input csrf-token="AB56" 를 들고 있어야하고 post 요청방식 일때 가능 get은 안됨.

 

현대적인 자바스크립트 ajax 통신할것이기 때문에 이거 안쓴다. csrf-token비활성화

 

http.csrf().disable(); 

 

 

이런 방식은 리액트로하면 어차피 모든 걸 data로 리턴하니까 jwt써야 한다.

 

 

 

-----------------------------------------이까지가 회원가입.

 

 

 

 

마이바티스말고 JPA!!

ORM

 

톰켓시작부터 JPA가 ORM해준다!!

 

 

javax.persistence.Entity;

@Entity

 

 

오라클은 sequence전략 

MyAQL autoIncrement : 이전거보고 하나 증가

 

 

 

 

ddl : 정의(DROP......)

 

톰켓시작시에 디비에 테이블이 생긴다.

 

jpa너무 좋음.

 

저절로 테이블 생김.

 

 

Hibernate :  ORM프레임워크임.

 

원래 mysql은 _로 되어있음.

대문자로 단어 구분하고 싶으면 아래와같이 application.yml에 

      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

을 설정하면 된다.

 

 

회원가입은 되지만 로그인은 안됨.

 

왜냐하면

시큐리티는 password가 데이터베이스 테이블에 해쉬로 데이터가 저장되기때문에

이전에 테이블에 숫자로 그냥 저장된 데이터로는 로그인이 되지 않는다.

 

jsp에서 sha256로 암호화했었는데 Bcrypt는 스프링이 시큐리티를 들고 있고 시큐리티에 Bcrypt를 이미 들고 있다!!

 

Bcrypt암호화!

 

 

 

 

athentication 객체를 만드는게 목적

 

토큰만들어서 Authentication Manager한테 던져서 로그인 처리해준다. 

UserDetailService한테 아이디 패스워드를 던져서 UserDetails를 돌려준다.

 

 

 

 

세션에 함부로 접근 못하도록 이렇게 꽁꽁 싸매놨다.

 

내가 강제로 세션에 등록하고 싶다면 AuthenticationManager만 DI해서 내가 접근해서 하면 된다.

 

레거시 때 부터

 

UserDetailsService

PrincipalDetailsService가  UserDetailsService를 덮어쓰고 메모리에 뜬다. (IoC컨테이너에 등록된다.)

 

인터페이스 

 

 


@Entity

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY) 

@CreationTimestamp

 

 


 

 

이 시큐리티 보안 뚫을 라면 마샬링해야 함.