리플렉션

스프링 구동 -> 스프링 컨텍스트가 램에 할당 -> 

(스프링 컨텍스트)

 

-> 어노테이션 스캔( 컴포넌트 스캔  )

(스캔 하는 위치)

스캔 하는 것을 리플렉션이라고 한다

---

리플렉션 - 실행 타임에 메모리를 찾아서 IOC된 객체를 찾는다
(ex 컨트롤러 실행시 IOC객체 찾기)

--------------

 

톰캣 실행 -> 스프링 실행

 

필터

1차 필터 - 톰캣이 가지고 있는 web.xml

2차 필터 - 스프링의 인터셉터

 

필터 또는 인터셉터를 설정 한다는 것은

기본으로 사용하는 필터를 disable하거나

기본으로 사용하지 않는 필터를 enable하거나

내가 직접 필터를 커스텀 하는 것

 

톰캣의 필터와 스프링의 인터셉터가 합쳐 쓰는 것을 시큐리티 라고 한다.

추후 webMvcConfigurer 가 다른것으로 바뀐다면 인터셉터에 접근하는 방법을 찾아야한다
(WebFlux 등)

인터셉터 + 필터 = 시큐리티

 

AOP =관점 지향 프로그래밍 - 함수의 직전과 직후를 처리할 수 있다

회원가입
직전 - 유효성체크
본문 - 회원가입
직후 - 세션등록 및 로그인처리

직전과 직후의 부가적인 기능을 밖으로 빼고 본문의 기능(관심 로직)을 작성

부가적인 기능은 [공통적]으로 쓸 수 있게 작성해놓고 사용 !! -> 핵심

-------

레거시 사용시

web.xml ------- 톰캣 시작시 발동

root-context.xml  -------- 메모리에 딱 1번만 올릴 것들 (DB관련 등) // 톰캣 시작시 발동
객체의 생성 및 관리


servlet-context.xml -------- 요청 올 때마다 메모리에 띄울 것들 // Request할 때 발동된다

----------

aop는 요청시마다 생겨야하니까 servlet-context.xml

----------

 

인터셉터 요약

1. @Configuration으로 설정파일 지정
2. 설정파일에 WebMvcConfigurer을 implements
3. 인터셉터만 구성하기위해 addInterceptors() 오버라이딩
4. registry에 인터셉터 추가 / 주소패턴 추가
5-1. 인터셉터 return true( 컨트롤러 함수진입 )
5-2. 인터셉터 return false( throw new Exception() )
6. @ControllerAdvice를 어노테이션한 익셉션 핸들러 진입
7. @ExceptionHandler(value = 익셉션이름.class)인 함수 실행

 

인터셉터용 자바파일 생성

 

 

 

 

인터셉터를 사용하기위해서 WebMvcConfigurer를 임플리먼트 한다

 

 

설정파일에는 @Configuration 을 추가

addInterceptors 인터셉터를 추가하면 WebConfig 클래스는 인터셉터의 역할을 하게 된다.

WebMvcConfigurer.super.addInterceptors(registry); 를 삭제한다.

 

 

(Dispatcher Servlet에서 스프링으로 보낼때 사이에서 핸들러가 중간에 낄 수 있다.)

핸들러 - 주소매핑( 핸들러 매핑 -> 디스패쳐서블릿 -> 핸들러 어댑터 -> 인터셉터(?) -> 컨트롤러 )

 

 

프리핸들러로 컨트롤러의 함수에 진입하기 직전을 컨트롤 할 수 있다.

아래는 HandlerInterceptor 인터페이스를 new 해서 preHandle을 오버라이딩 한 상태

 

 

HandlerInterceptor 인터셉터를 커스텀해주자

 

HandlerInterceptorAdapter를 상속받아서 인터셉터 클래스를 만든다

 

 

 

WebConfig.java에 위에서 커스텀 해준 인터셉터들을 넣고

PathPatterns를 각각 설정해준다

 

 

실행해서 /user 하위경로를 request하면 자동으로 인터셉트한다.(세션을 체크해야함 메시지 확인)

 

 

커스텀한 인터셉터에서 세션 등을 확인하여 

문제가 있을시 컨트롤러 함수로 진입하지 않고 메세지를 띄운 뒤 다른 페이지로 리다이렉션 시킨다

문제가 없을시 컨트롤러 함수로 이동

 

 

로그인 하지 않고 진입시 화면

 

 

로그인 후 진입시 접속된다

 

 

위와 마찬가지로 RoleIntercepter도 세팅

( 스샷의 오류 : principal.getRole() 앞에 !를 넣어야한다)

 

 

 

로그인을 해도 어드민이 아니라면 익셉션

 

 

어드민으로 로그인해서 접속하면 관리자페이지로 접속

 

 

위와 같이 컨트롤 해도 되나 익셉션을 통한 핸들링도 가능하다

핸들러 패키지 추가

 

 

(주석과 같이 익셉션별로 구분해야하나 지금은 Exception을 넣음)

 

 

익셉션을 throw 하면 이 파일로 연결되어 리턴

@ControllerAdvice를 어노테이션하면 throw 한 익셉션이 이 파일로 이동된다

그리고 @ExceptionHandler에 맞는 익셉션을 찾아서 함수로 진입한다

 

 

throw new Exception() 을 이용하여 익셉션을 개발자가 낚아채도록 한다

 

 

익셉션을 통한 권한체크

 

 

익셉션을 커스텀 하기 위해 파일 생성

 

 

Exception을 상속받는다

 

 

커스텀한 익셉션을 입력한다

 

 

익셉션 핸들러에도 커스텀한 익셉션을 적용한다

 

 

IO익셉션으로 설정해놓으면 터진다 ( 함수가 없기 때문(?))

 

 

 

----------

로그기록 api

https://sentry.io/welcome/

 

Application Monitoring and Error Tracking Software

Self-hosted and cloud-based error monitoring that helps software teams discover, triage, and prioritize errors in real-time.

sentry.io

-----------

 

https://blog.naver.com/getinthere/221718319587

 

springboot 8강 - Spring 인터셉터

인터셉터란 PPT아래와 같이 두 가지만 파일만 정의해주면 된다.config/WebMvcConfig.javaconfig/Ses...

blog.naver.com

 

핸들러는 인터셉터다

 

Spring+HandlerInterceptor.pptx
0.64MB

 

 

 

---

컨트롤러 - 뷰리졸버 발동 (@ResponseBody쓰면 미발동)

Rest컨트롤러 - 뷰리졸버 미발동

------

스프링 리퀘스트 라이프 사이클

-------------

 

 

Dispatcher Servlet 에서 FrontController 타고 Intercepter가 있으면 탄다

 

 

 

 

 

 

postHandle도 이용할 수 있으며 modelAndView 라는 객체도 가지고 있다

modelAndView 는 JSP에서의 모델이다
response 시 같이 가져가게된다

 

 

프리핸들러 - 세션 등을 확인

 

 

 

본문내용은 여기 까지 입니다.

-------------------------------------------

로그아웃

 

redirect: 를 사용하면 파일이 아닌 주소를 검색한다

 

-----------

 

글쓰기

 

세션 인터셉터에 등록

 

 

 

---------------------

디폴트로 만들어진 인터페이스는 구체화하지 않아도 오류가 나지 않는다

----------------

Log4J Logger

-------------

 

-----

마샬링

------

세션서버

리액트 있는 조는 이렇게 만들면 안됨 - jwt 세팅해야함

템플릿을 이용하는 조는 세션서버를 만들어야 한다 - csrf-token 비활성화 등 세팅

----

옵저버 패턴이 적용 되어 있는 리액티브 스프링

----

스프링 시큐리티 보안 공부

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

 

Securing a Web Application

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

------

 

 

 

 

 

 

spring security / spring data JPA 로 세팅

 

 

com.jaybon.securityEx01 아래에 만들어야 컴포넌트 스캔이 된다

 

 

DataSource (DB 풀링 해주는 객체)

 

 

yml파일로 변경

 

 

포트와 컨텍스트패스 캐릭터셋을 설정하고 enable force

server:
  port: 8080
  servlet:
    context-path: /
    encoding:
      charset: utf-8
      enabled: true
      force: true

 

 

 

 

jdbc:mysql://localhost:3306/security?serverTimezone=Asia/Seoul

(security라는 데이터베이스에 접속한다는 뜻)

 

 

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?serverTimezone=Asia/Seoul
    username: cos
    password: cos1234

 

 

(mysql db연결)

https://blog.naver.com/getinthere/221708608489

 

JSP AWS 배포 하기 - MySQL + Tomcat

https://youtu.be/BH7De5EEoU4​만약에 AWS에 배포한 프로젝트 내부의 META-INF의 context...

blog.naver.com

 

 

 

 

실행 해보면 잠겨있다

인터셉터에서 막힌 것

각종 공격을 다 막아 준다

 

 

필터 - 디스패쳐 - 인터셉터 - 컨트롤러

 

 

로그에 찍힌 패스워드를 입력

비밀번호는 (해시)로 되어 있다

 

 

 

 

세션

Security-Context (key) 밑에 방대한 값(value)들이 있다

그 중에

Authentication( 인증에 필요한 권한, 유효한 이용자인지 등 모든 필드가 정해져 있다 )

필드들이 정해져 있다는 것은 만들어서 넣어야 한다는 뜻

Authentication Manager의 도움을 받아서 Authentication을 만든다

Authentication의 필수 입력 값은 (username, password)

Authentication의 구성은 정해진 필드를 따라 만들어야 한다 ( User, UserDetails )

UserDetails ( 유저네임, 패스워드, 권한 )를 만들 때 컴포지션하거나

내 커스텀 유저정보 java 파일에 UserDetails을 extends 하면 된다

접근할 때 DI를 사용하면 된다

 

 

로그아웃 하려면

http://localhost:8080/logout

 

 

----------

로그인 페이지 회원가입 페이지를 커스텀 할 것

 

 

설정파일 하나 생성

 

필터 - 디스패쳐 - 인터셉터 - 컨트롤러

 

필터와 디스패쳐 인터셉터 사이에

시큐리티 필터 체인 ( 많은 필터가 모여있다, xss, 주소, ip, 인증 등) - 체인이 있다는 것을 기억

필터를 낚아채려면 오버라이딩 또는 extends로 재정의

 

 

전체 필터를 관리할 수 있는 클래스 (@EnableWebSecurity)

 

어댑터가 있다는 것은 일부 원하는 것만 오버라이딩 할 수 있다는 것

 

 

 

 

http요청을 제어

 

 

 

 

로그인 없이 바로 들어가진다

 

 

 

 

 

 

다른페이지로 이동하면 권한이 없어서 페이지가 뜨지 않는다(403)

 

 

위의 방식이 파즈티브 방식(열것만 열고 나머지는 다 잠그기)이고 아래는 네거티브 방식(다열고 잠글것만 잠그기)

 

 

 

 

http://localhost:8080/admin -> http://localhost:8080/login

(파일이 없어서 404)

 

 

로그인을 리턴해주는 라우팅을 만들면

 

 

 

 

머스태치 

 

메이븐 리파지토리에서 spring mustache 검색

 

 

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

 

 

추가해주고 서버끄고 메이븐리파지토리 업데이트 무조건!

 

 

또는 yml 파일에

  mvc:
    view:
      prefix: /templates/
      suffix: .mustache

 

 

 

 

템플릿에서 name을 잘 적어줘야한다

 

 

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

 

 

레파지토리

jpa는 어노테이션이나 컨피그 데이터 소스가 아니라 JpaRepository를 상속

 

 

컨트롤러에서 DI

 

 

한줄추가

 

 

입력해보면 들어가있다

(로그인시 오류가 날것이다 암호화가 되어있지않음)

 

BCryptPasswordEncoder (안좋은방법 다른방법 쓸 것)

encode

 

 

SecurityConfig.java

 

 

IndexController.java

 

 

bCryptPasswordEncoder를 이용해 해시화 시켜줌

 

 

로그인

10. Authentication 객체 생성

Authentication은 AuthenticationFilter의 자식

AuthenticationFilter는 loginProc가 호출될 때 작동

UsernamePasswordAuthenticationToken 토큰이 있어야 로그인됨

 

https://getinthere.tistory.com/29

 

스프링부트 with JPA 블로그 13강 - 시큐리티 동작 원리

1. 스프링 mvc request life cycle 2. Filter와 Interceptor는 실행 시점이 다르다. Filter는 WebApplication에 등록 - web.xml Interceptor는 Spring의 Context에 등록 필터체인 예제와 인터셉터 예제하기 3. In..

getinthere.tistory.com

 

 

1아이디패스워드받아서

2토큰을받고

3유저디테일서비스가 받음

4유저디테일서비스는 유저디테일즈를 리턴

5어썬티케이션매니저가 받아서 어썬티케이션에 넣는다

6유저디테일은 시큐리티에 꼭 필요한 필드들이 있기 때문에 무조건 유저디테일로

7내가 만든 유저 모델을 유저디테일 타입으로 바꿔줘야한다

8어썬티케이션은 세션에 담긴다
(Map<String, Authentication> 객체이름 = new HashMap<>();)
(aa.put("Security-Context", auth))
(session.setAttribute("Security-Context-Holder", 해시맵))
쉽게 접근 못하도록 싸매져 있다

AuthenticationManager를 이용해서 Authentication를 저장할 수 있다(강제로 저장)

 

 

패키지 생성

 

 

유저디테일즈를 리턴해주기 위해서 클래스 하나 생성

모델 유저에 유저디테일즈를 상속받으면 유저모델이 망가지기 때문에 새로만들어줌

 

 

UserDetails를 임플리먼트해주고 오버라이딩

Authentication 객체에 저장할 수 있는 유일한 타입 - UserDetails

시큐리티 입장에서 관리해줄 수 있게 정해져 있다

 

 

User 모델 콤포지션

더보기
package com.jaybon.securityEx01.config.auth;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.jaybon.securityEx01.model.User;

import lombok.Data;


//Authentication 객체에 저장할 수 있는 유일한 타입
@Data
public class PrincipalDetails implements UserDetails{
	
	private User user;
	
	public PrincipalDetails(User user) {
		super();
		this.user = user;
	}
	
	

	@Override // 사용자의 비밀번호를 알고 싶으면 호출
	public String getPassword() {
		return user.getPassword();
	}

	@Override // 사용자의 유저네임를 알고 싶으면 호출
	public String getUsername() {
		return user.getUsername();
	}

	@Override // 사용자가 만료된 지를 알고 싶으면 호출
	public boolean isAccountNonExpired() { // 만료안됐니?
		//접속시간확인하여 true false 리턴
		return true;
	}

	@Override 
	public boolean isAccountNonLocked() { // 락 안걸렸니?
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() { // 계정활성화 되어있니?
		return true;
	}
	
	@Override // 어떤 권한을 가졌니?
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		return null;
	}

}

 

 

 

 

UserDetailsService를 만들어야함

 

 

JPA 쿼리 짜는법

 

jpa 쿼리 생성룰

https://papababo.tistory.com/272

 

[Spring Data Rest] Query creation - 쿼리 생성 룰

Spring Data Rest 사용시, 또는 JPA 기본 검색기능활용시, 아래의 네이밍 룰 따르면 끝! https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation Table 4. Suppo..

papababo.tistory.com

 

 

로그인 해보면 성공

 

-------

권한리턴하기

유저 권한 리턴하기 (주석은 Arrays)

스프링 내부에서 원하는 GrantedAuthority 타입으로만 설정해서 리스트에 저장하여 리턴

 

 

----------

 

구조

 

PrincipalDetails.java

더보기
package com.jaybon.securityEx01.config.auth;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.jaybon.securityEx01.model.User;

import lombok.Data;


//Authentication 객체에 저장할 수 있는 유일한 타입
@Data
public class PrincipalDetails implements UserDetails{
	
	private User user;
	
	public PrincipalDetails(User user) {
		super();
		this.user = user;
	}
	
	

	@Override // 사용자의 비밀번호를 알고 싶으면 호출
	public String getPassword() {
		return user.getPassword();
	}

	@Override // 사용자의 유저네임를 알고 싶으면 호출
	public String getUsername() {
		return user.getUsername();
	}

	@Override // 사용자가 만료된 지를 알고 싶으면 호출
	public boolean isAccountNonExpired() { // 만료안됐니?
		//접속시간확인하여 true false 리턴
		return true;
	}

	@Override 
	public boolean isAccountNonLocked() { // 락 안걸렸니?
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() { // 계정활성화 되어있니?
		return true;
	}
	
	// Arrays.asList(new SimpleGrantedAuthority(user.getRole()));
	@Override // 어떤 권한을 가졌니?
	public Collection<? extends GrantedAuthority> getAuthorities() {
		
		Collection<GrantedAuthority> authList = new ArrayList<>();
		authList.add(new SimpleGrantedAuthority(user.getRole()));
		return authList;
		
	}

}

PrincipalDetailsService.java

더보기
package com.jaybon.securityEx01.config.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.jaybon.securityEx01.model.User;
import com.jaybon.securityEx01.repository.UserRepository;

// UserDetailsService는  IoC로 찾음

@Service // UserDetailsService타입으로 메모리에 뜬다 (덮어씌워짐)
public class PrincipalDetailsService implements UserDetailsService{
	
	@Autowired
	private UserRepository userRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// 어썬티케이션 매니저가 낚아챔
		// JPA는 기본적인 CRUD만 있어서 다른걸 쓰려면 만들어줘야함 
		
		User user = userRepository.findByUsername(username);
		
		if(user == null) {
			return null;
		}
		
		return new PrincipalDetails(user);
	}

}

SecurityConfig.java

더보기
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("/"); // 성공하면 해당 주소로 이동 / 슬래시만 달면 이전 주소로 이동
	}
}

IndexController.java

더보기
package com.jaybon.securityEx01.controller;

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

import com.jaybon.securityEx01.config.auth.PrincipalDetails;
import com.jaybon.securityEx01.model.User;
import com.jaybon.securityEx01.repository.UserRepository;

@Controller
public class IndexController {
	
	@Autowired
	private UserRepository userRepository;
	
	@Autowired
	private BCryptPasswordEncoder bCryptPasswordEncoder;

	@GetMapping({ "", "/" })
	public @ResponseBody String index() {
		return "인덱스 페이지입니다";
	}

	@GetMapping("/user")
	public @ResponseBody String user(@AuthenticationPrincipal PrincipalDetails principalDetails) {
		System.out.println("확인"+principalDetails);
		System.out.println(principalDetails.getUser().getRole());
		System.out.println(principalDetails.getAuthorities()); // 출력 했을 때 사용자의 모든 권한을 리턴
		return "유저 페이지입니다";
	}

	@GetMapping("/admin")
	public @ResponseBody String admin() {
		return "어드민 페이지입니다";
	}

	@GetMapping("/login")
	public String login() {
		return "login"; // 머스태치를 pom에 추가했으니 서픽스는 templates 프리픽스는 .mustatche
	}

	@GetMapping("/join")
	public String join() {
		return "join";
	}

	@PostMapping("/joinProc")
	public String joinProc(User user) {
		System.out.println("회원가입 진행" + user);
		String rawPassword = user.getPassword();
		String encPassword = bCryptPasswordEncoder.encode(rawPassword);
		user.setPassword(encPassword);
		user.setRole("ROLE_USER");
		userRepository.save(user);
		return "redirect:/";
	}

}

User.java

더보기
package com.jaybon.securityEx01.model;

import java.sql.Timestamp;

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

import org.hibernate.annotations.CreationTimestamp;

import lombok.Data;

// ORM - Object Relation Mapping - 알아서 데이터베이스 테이블 만들어 준다

@Data
@Entity // 이것을 토대로 데이터베이스 모델을 만들 수 있다.
public class User {
	@Id // primary key를 걸어주는 어노테이션
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 오라클은 시퀀스 전략, mysql은 오토인크리먼트 전략
	private int id;
	private String username;
	private String password;
	private String email;
	private String role; // ROLE_USER / ROLE_ADMIN
	@CreationTimestamp
	private Timestamp createDate;
}

UserRepository.java

더보기
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 내맘대로();
	
}

join.mustache

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 페이지</title>
</head>
<body>
	<h1>회원가입 페이지</h1>
	<hr/>
	<form action="/joinProc" method="post">
		<input type="text" name="username" placeholder="username">
		<input type="password" name="password" placeholder="password">
		<input type="email" name="email" placeholder="email">
		<button>회원가입</button>
	</form>
</body>
</html>

login.mustache

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
</head>
<body>
	<h1>로그인 페이지</h1>
	<hr/>
	<!-- 시큐리티는 x-www-form-urlencoded 타입만 인식 -->
	<form action="/loginProc" method="post">
		<input type="text" name="username">
		<input type="password" name="password">
		<button>로그인</button>
	</form>
</body>
</html>

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
    
#  mvc:
#    view:
#      prefix: /templates/
#      suffix: .mustache


  jpa:
    hibernate:
      ddl-auto: update #create update none 3개 중 하나 선택
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
      
      
      

 

 

 

'Server > Spring Boot' 카테고리의 다른 글

spring boot // 리플렉션  (0) 2020.08.01
spring boot // 필터 / 인터셉터  (0) 2020.08.01
spring boot // 블로그 연습  (0) 2020.07.27
spring boot // 주의사항  (0) 2020.07.27
spring boot // web.xml  (0) 2020.07.27

 

 

없어도 잘돌아 간다고함

 

 

깃에 커밋하면서 하자

만들어두자

 

 

디비 구조에 따라 모델을 만들어주자

 

 

 

 

jsp때 만든 ui를 가져다 사용하자

 

 

 

 

 

 

header.jsp로 가서 회원가입과 로그인 주소를 만들자

 

 

(스크립트)1번유저정보는 1번유저만 볼수 있다 - 로그인이 되어있어야한다 - 2가지가 필요 ( 인증 + 권한 )

1번유저정보 (인증 + 권한)
1번유저수정 (인증 + 권한)
1번유저삭제 (인증 + 권한)
-> /user/~~~~~~

2번 회원가입 페이지 이동, 회원가입시 ()
2번 로그인 페이지 이동 ()
-> /auth/~~~~~~

라이브러리를 사용할 때 이해하게 된다

 

 

 

 

DataSourceConfig.java 삭제

 

fail to refresh live data from process 에러가 뜰 경우

pom.xml에

		<!-- 스프링부트 스타터 액츄에이터 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

을 추가해보자

 

 

 

 

SPA 싱글페이지 애플리케이션 내부적으로 ajax

 

웹브라우저 안드로이드 리액트 공용 서버를 만들려면

페이지가 아닌 데이터를 리턴받는 서버를 만들어야한다

 

get요청을 제외한 모든 요청을 데이터를 리턴하는 서버로 제작

 

 

 

 

 

 

자바스크립트를 줬으니 아이디를 주고 타입을 버튼으로 바꾸자

 

 

앞에 /를 붙여주면 static 으로 이동한다

 

 

-----------------------

디스 바인딩

 

화살표함수로 디스 바인딩

 

 

context-path 를 /로 해주자

포트도 8080

----------------------

 

 

get방식 빼고는 자바스크립트 방식으로 통일

모든 요청은 자바스크립트 !

 

 

폼태그 내용을 지우자

 

 

폼 인풋에 name 을 적는 것은 옛날방식이다

 

 

 

 

자바스크립트 로직 추가

더보기
let index = { //여기서는 이벤트 리스너를 바인딩만 하고
	init : function() {
		
		$("#btn-save").on("click", ()=> {
			this.save();
		});
		
		$("#btn-update").on("click", ()=> {
			this.update();
		});
		
	},
	
	save: function() { // 실제 로직은 여기서 실행
		alert("btn-save 로직 실행");
		let data ={
				username : $("#username").val(),
				password : $("#password").val(),
				email : $("#email").val()
		};
		alert("btn-save data");
		
		$.ajax({ // 공식!
			
			type:"post",
			url: "/auth/joinProc",
			data: JSON.stringify(data),
			contentType: "application/json; charset=utf-8",  //http에서는 Content-Type 라고 씀
			dataType: "json"  // 스프링은 응답할때 스트링일 경우 무조건 json으로 응답한다
			
		}).done((resp)=>{
			console.log(resp);
		}).fail((error)=>{
			console.log(error);
		});
		
	},
	
	update: function() { // 실제 로직은 여기서 실행
		alert("btn-update 로직 실행");
	}
}

index.init();

 

 

 

 

 

 

 

 

 

 

이해하기위해서 이렇게 테스트해보자 (나중에는 response 엔티티를 사용)

 

 

 

 

#{   } 변수명만적으면 알아서 getter를 호출할 수 있다

 

 

redayState가 4면 잘 들어갔다는 뜻

 

 

 

 

select가 아닌 delete insert update를 사용할 때
ok가 아닌 엔티티를 하나 만들어서 항상 같은 값을 리턴해주자 

 

 

 

 

 

 

 

 

 

 

ResponseEntity<?> 를 사용해도된다 // 나중에 쓸 것

 

 

결과

 

 

 

 

try catch를 안만들어두면 ajax자체를 실패하여 fail로 가게된다
그렇게 처리해도 되지만 fail에서 처리하지않고 done에서 처리하려면 try catch를 사용해본다

나중에는 핸들러를 이용할 것이다

트라이캐치를 쓰면 오류를 찾기 어려워지기 때문에 로그를 남겨야한다
그렇기 때문에 쓰지않는 것이 좋다

 

 

 

 

우리는 에러가 터질 때 낚아 채서 처리할 것이다 

 

 

리턴을 보이드로

 

result 를 없애고

 

 

fail로 이동

----------------------------

 

 

login도 폼에서 메소드와 액션을 지우고 인풋의 name 속성을 지운다

 

----------------

컨텍스트 - 이벤트를 받을 수 있다

-------------

 

 

 

 

 

리파지토리

 

 

맵퍼

 

 

서비스

 

 

컨트롤러

 

 

----------------

마이바티스 설정들 나중에 공부! 확인

https://mybatis.org/mybatis-3/ko/index.html

 

MyBatis – 마이바티스 3 | 소개

마이바티스는 무엇인가? 마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와 ��

mybatis.org

-------------------

 

 

---------------------

퍼시스턴스란 rs를 자바 객체에 넣어 주는 것

----------------------------

 

--------------------------

 

 

 

 

 

 

 

----------------

 

ObjectUtils.isEmpty(persistUser)

널 또는 빈객체인지 확인

 

 

 

 

 

 

 

----------------

컨트롤러는 무조건 서비스를 호출해야한다 (리파지토리 안됨)

----------------

디스패쳐 서블릿 - 프론트컨트롤러 - 컨트롤러들

-----------------

Controller는 뷰리졸버가 가능하다 (데이터를 주고받을 때 @ResponseBody)

RestController는 데이터만 리턴한다

----------------

// Controller, Repository, Configuration, Service, Component

// RestController, Bean

------------------

Service를 이용하면 트랜잭션이 발동함

Component는 특별한 역할이 없다

Bean은 클래스가 아닌 메서드에 묶인다

-------------------

https://private.tistory.com/39

 

스프링(Spring) - DI(Depedency Injection) 개념과 예제 : setter() 사용

예제 파일 : 이번 포스트에서는 스프링의 핵심 기능중 하나인 DI(Dependecy Injection)에 대해 알아보고 예제를 작성해보겠습니다. DI는 말 그대로 의존성을 주입시켜준다- 입니다. 객체를 직접 생성하

private.tistory.com

-----------------

 

 

 

 

 

 

 

----------

web.xml 에는 스프링 필터가 있다
종류가 많은데 중요한 것만 확인하자

message converter -> 기본전략이 xxx-from-urlencoded 즉 key=value 데이터만 파싱하려고한다
@RequestBody 를 걸어두면 들어오는 데이터를 확인하여 제이슨이면 메세지 컨버터를 체인지 한다
gson과 비슷한 오브젝트 매퍼가 동작된다 (그것을 동작시켜주는 것이 jackson이다)

 

추후에 메시지컨버터를 직접 바꿀 수도 있다

----------------

'Server > Spring Boot' 카테고리의 다른 글

spring boot // 블로그 연습  (0) 2020.07.27
spring boot // 주의사항  (0) 2020.07.27
spirng boot // 서비스 연습  (0) 2020.07.27
spring boot // 스프링 부트 세팅 요약  (0) 2020.07.27
spring boot // 퍼시스턴스  (0) 2020.07.27

'Server > Spring Boot' 카테고리의 다른 글

spring boot // 주의사항  (0) 2020.07.27
spring boot // web.xml  (0) 2020.07.27
spring boot // 스프링 부트 세팅 요약  (0) 2020.07.27
spring boot // 퍼시스턴스  (0) 2020.07.27
spring boot // dispatcherServlet / 어노테이션  (0) 2020.07.27

 

스프링 부트 세팅

Spring Web

SpringBoot Devtool

Lombok

MySQL

MYbatis

---------

JSTL

Tomcat-Embed-Jasper

-----------

테이블생성

------------

1 properties 
yml 확장자 변경
DB연결정보넣기
JSP view 경로 설정 (ViewResolver)

2 config 폴더생성
(복붙)
DataSourceConfig.java(참고 : yml 설정을 참고)
DataAccessConfig.java(참고 : DataSource와 Mapper)

3 Mapper 경로에 UserMapper.xml 생성 및 파일 세팅

4 User 클래스 만들기

5 UserRepository 만들기

6 jsp테스트 파일 만들기

7 TestController 생성 및 테스트

 

------------------

 

이름과 패키지명을 설정해준다

 

 

필요한 디펜던시를 고른다

 

 

외부에서 필요한 디펜던시들을 가져온다

 

 

 

 

 

 

 

 

외부 디펜던시들을 pom.xml에 넣는다

 

 

application.yml

server:
  port: 8000
  servlet:
    context-path: /blog

spring:  
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
      
  datasource:
    url: jdbc:mysql://localhost:3306/spring?serverTimezone=Asia/Seoul
    username: spring
    password: bitc5600
    driver-class-name: com.mysql.cj.jdbc.Driver

properties파일을 yml로 바꾸고 세팅해준다

 

 

컨피그 파일을 만든다

 

 

 

 

DataAccessConfig.java

package com.cos.demo.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@Configuration
@MapperScan(basePackages = "com.cos.blog.repository") // 옆의 경로 이하 파일을 메모리에 다띄워준다(@repo~~ 안해줘도됨)
public class DataAccessConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(
        		new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    
}

 

 

DataSourceConfig.java

package com.cos.demo.config;

import javax.sql.DataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DataSourceConfig {

	@ConfigurationProperties(prefix="spring.datasource")
	public DataSource dataSource(){
    	return DataSourceBuilder.create().build();
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---------------------

+ Recent posts