(요청)
사용자 <---------> 서버
(로그인페이지)
서버에서 인증하는 것이 아니라 구글 페이스북에 먼저 인증을 요청
사용자 ----------> 구글 페이스북 ( 로그인 )
구글 페북에서 인증되면 서버에 코드를 준다
구글 페이스북 -------> 서버 (코드를 준다)
서버는 코드를 이용해서 구글 페이스북 액세스 토큰을 요청한다
토큰을 받으면 (권한을 받은 것)
서버 -------> 구글 페이스북 (토큰요청)
구글 페이스북 -------> 서버 (토큰을 준다)
액세스 토큰으로 스코프를 요청 할 수 있다
서버 -------> 구글 페이스북 (스코프요청)
구글 페이스북 -------> 서버 (사용자 정보 스코프를 준다)
일반로그인은
provider:
prividerId:
가 있는 사람은 못하게 막는다
User{
id: 자동증가값
username: 프로바이더_프로바이더 아이디
password: 임의의 문자열을 해시값으로 만들어 입력
emaill: 스코프의 이메일
provider: 프로바이더
prividerId: 프로바이더 아이디
}
Security-Context (key) 밑에 방대한 값(value)들이 있다 그 중에 Authentication( 인증에 필요한 권한, 유효한 이용자인지 등 모든 필드가 정해져 있다 ) 필드들이 정해져 있다는 것은 만들어서 넣어야 한다는 뜻 Authentication Manager의 도움을 받아서Authentication을 만든다 Authentication의필수 입력 값은 (username, password) Authentication의 구성은 정해진 필드를 따라 만들어야 한다 ( User, UserDetails ) UserDetails ( 유저네임, 패스워드, 권한 )를 만들 때 컴포지션하거나 내 커스텀 유저정보 java 파일에UserDetails을 extends 하면 된다 접근할 때 DI를 사용하면 된다
----------------
시큐리티
요약
1. 프로젝트 생성
2. Spring Security 디펜던시 추가
3. yml 파일 설정
4. DB 생성
5. 서버 가동 및 로그인 로그아웃 테스트 (비밀번호는 콘솔창의 해시값)
6. SecurityConfig파일 생성 및 @Configuration @EnableWebSecurity 추가
6-1. WebSecurityConfigurerAdapter 상속
6-2. @EnableGlobalMethodSecurity(prePostEnabled = true) 추가
6-3. configure(HttpSecurity http) 오버라이딩
6-4. http객체에 설정하기
6-5. 폼태그의 post 요청시 거부를 당하지 않기 위해 http.csrf().disable(); 추가
새 스프링부트 프로젝트 생성
파일명 그룹 패키지 설정
spring security / spring data JPA를 세팅해서 연습해본다
템플릿을 바로추가하려면 여기서 머스태치나 타임리프를 사용
참고사항 : com.jaybon.securityEx01 아래에 만들어야 컴포넌트 스캔이 된다
IDENTITY로 설정 (오라클은 SEQUENCE를 사용, IDENTITY는 해당 DB특유의 전략 사용)
자바모델 만들어 질 때 테이블 생성
자바모델 그대로 데이터베이스에 테이블이 생성된다
(생성 create 업뎃만 update 아무것도안하려면 none)
update 만 선택해도 테이블생성까지 가능하다!
mysql에서 셀렉트해보면 만들지도 않은 테이블이 생성되어 있다
모델에서 createDate를 만들고 저장만 하면!
@CreationTimestamp 세팅 (시간 자동입력)
(java.security -> java.sql 로 만들어야한다)
DB에서 속성이 자동으로 생성되어있다
회원가입 해보면
서버를 켜보면 하이버네이트 Hibernate
(서버를 켤때 마다 지워지고 다시 만들어진다)
디폴트는 언더바 전략
네이밍 전략
커멜 표기법 전략으로 변경
jpa:
hibernate:
ddl-auto: update #create update none 3개 중 하나 선택
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
8어썬티케이션은 세션에 담긴다 (Map<String, Authentication> 객체이름 = new HashMap<>();) (aa.put("Security-Context", auth)) (session.setAttribute("Security-Context-Holder", 해시맵)) 쉽게 접근 못하도록 싸매져 있다
AuthenticationManager를 이용해서Authentication를 저장할 수 있다(강제로 저장)
package com.jaybon.securityEx01.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration // IoC 빈(bean, 인스턴스)을 등록
@EnableWebSecurity // 필터 체인 관리 시작 어노테이션
@EnableGlobalMethodSecurity(prePostEnabled = true) // 컨트롤러 접근 전에 낚아챔, 특정 주소 접근시 권한 및 인증 미리체크
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Bean // IoC에 등록되어 컨피그가 호출될 때 생성, 메서드를 IoC하는 방법
public BCryptPasswordEncoder enc() { // 마땅히 둘 곳이 없어서 둔 것 Controller를 제외한 곳에 둠
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // csrf 비활성화
http.authorizeRequests()
.antMatchers("/user/**", "/admin**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.formLogin()
.loginPage("/login") // 인증이 필요한 곳에 /login 으로 리다이렉트
.loginProcessingUrl("/loginProc") // 필터체인에서 인지하고 있다가 시큐리티가 낚아채서 Authentication Manager
.defaultSuccessUrl("/"); // 성공하면 해당 주소로 이동 / 슬래시만 달면 이전 주소로 이동
}
}
package com.jaybon.securityEx01.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.jaybon.securityEx01.model.User;
// JpaRepository를 상속하면 자동 스캔됨.
public interface UserRepository extends JpaRepository<User, Integer>{
//Jpa Naming 전략
// SELECT * FROM user WHERE username = ?
User findByUsername(String username); // 함수이름에 맞게 쿼리가 동작한다
// // SELECT * FROM user WHERE username = ? AND password = ?
// User findByUsernameAndPassword(String username, String password);
//
// @Query(value = "SELECT * FROM user", nativeQuery = true)
// User 내맘대로();
}
loginProc는 컨트롤러에서 낚아채는 것이 아니라 loginProcessingUrl에서 낚아채서 수행
(formLogin이라면 템플릿에서 form타입으로 날려야한다)
성공하면 해당주소로 이동 defaultSuccessUrl (Ajax와 같이 쓰지말 것 : 응답이 두번되기 때문에 꼬임)
로그인만! Ajax 쓰지말자 (회원가입은 써도됨)
컨트롤러에 회원가입 라우팅 추가
템플릿에 회원가입 추가 (회원가입은 ajax로 바꾸어도 무방)
컨트롤러에 회원가입 프로세스 라우팅 추가
(시큐리티 컨피그를 안만들었기 때문)
@RequestBody는 제이슨 일때만!
유저모델추가
입력 테스트
포비든이 뜬다 무엇이 문제일까
POST일때만 폼태그로 요청 토큰(csrf-token)이 필요하다!
(csrf = 해커가 임의대로 요청을 해서 공격)
csrf-token을 임시로 만들어줘서 줘야한다
(스프링에서 csrf 토큰 만들기 검색 공부)
방법(1. csrf토큰 비활성화 // 2. 토큰 만들기)
현대 프로그래밍은 자바스크립트로 하기 때문에 csrf를 잘 당하지 않는다 (수업에선 비활성화)
SecurityConfig.java
회원가입을 하면 인덱스페이지로 이동된다
-------
JPA
연습 용이라 서비스 안만들고 레파지토리로 끝냄
모델에서 @Entity를 추가(데이터베이스의 모델)
IDENTITY로 설정
모델 만들어 질 때 테이블 생성
(생성 create 업뎃만 update 아무것도안하려면 none)
mysql에서 셀렉트해보면 만들지도 않은 테이블이 생성되어 있다
모델에서 createDate를 만들고 저장만 하면!
@CreationTimestamp 세팅 (시간 자동입력)
DB에서 속성이 자동으로 생성되어있다
회원가입 해보면
서버를 켜보면 하이버네이트 Hibernate
(서버를 켤때 마다 지워지고 다시 만들어진다)
디폴트는 언더바 전략
네이밍 전략
커멜 표기법 전략으로 변경
jpa:
hibernate:
ddl-auto: update #create update none 3개 중 하나 선택
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
8어썬티케이션은 세션에 담긴다 (Map<String, Authentication> 객체이름 = new HashMap<>();) (aa.put("Security-Context", auth)) (session.setAttribute("Security-Context-Holder", 해시맵)) 쉽게 접근 못하도록 싸매져 있다
AuthenticationManager를 이용해서 Authentication를 저장할 수 있다(강제로 저장)
package com.jaybon.securityEx01.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration // IoC 빈(bean, 인스턴스)을 등록
@EnableWebSecurity // 필터 체인 관리 시작 어노테이션
@EnableGlobalMethodSecurity(prePostEnabled = true) // 컨트롤러 접근 전에 낚아챔, 특정 주소 접근시 권한 및 인증 미리체크
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Bean // IoC에 등록되어 컨피그가 호출될 때 생성, 메서드를 IoC하는 방법
public BCryptPasswordEncoder enc() { // 마땅히 둘 곳이 없어서 둔 것 Controller를 제외한 곳에 둠
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // csrf 비활성화
http.authorizeRequests()
.antMatchers("/user/**", "/admin**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.formLogin()
.loginPage("/login") // 인증이 필요한 곳에 /login 으로 리다이렉트
.loginProcessingUrl("/loginProc") // 필터체인에서 인지하고 있다가 시큐리티가 낚아채서 Authentication Manager
.defaultSuccessUrl("/"); // 성공하면 해당 주소로 이동 / 슬래시만 달면 이전 주소로 이동
}
}
package com.jaybon.securityEx01.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.jaybon.securityEx01.model.User;
// JpaRepository를 상속하면 자동 스캔됨.
public interface UserRepository extends JpaRepository<User, Integer>{
//Jpa Naming 전략
// SELECT * FROM user WHERE username = ?
User findByUsername(String username); // 함수이름에 맞게 쿼리가 동작한다
// // SELECT * FROM user WHERE username = ? AND password = ?
// User findByUsernameAndPassword(String username, String password);
//
// @Query(value = "SELECT * FROM user", nativeQuery = true)
// User 내맘대로();
}