본문 바로가기
학원수업/4월

04/13 국비학원 개발자과정 - Spring Security

by 코딩마스터^^ 2023. 4. 13.
server:
  port: 5000
  servlet:
    context-path: /
    encoding:
      charset: UTF-8
      enabled: true
      force: true  
spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
      
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?serverTimezone=Asia/Seoul
    username: root
    password: tiger
#ddl-auto: create이면 매번 테이블을 만들어준다
#create전략이면 테이블을 삭제하고 새로 만들어 준다
#그래서 맨 처음 테이블이 만들어질 때만 생성하고 다음에 실행할 때는 update로 바꾸어 주어야함    
#show-sql을 true로 주면 콘솔창에 쿼리문이 출력됨
#hibernate.format_sql: true로 주면 쿼리문이 정렬이 되어서 출력됨
#physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 이것은
#Entity를 만들때(즉 테이블을 만들때) 변수명 그대로 테이블 컬럼으로 만들어준다는 의미임

#open-in-view:true 로 주면 Lazy로드가 가능해짐. false로 하면 영속성 컨텍스트가 service계층에서 종료됨
#영속성을 프리젠테이션 계층까지 가져간다. 트랜잭션은 Service계층에서 종료된다
#Transaction이 종료된 후에도 Controller의 Session이 close 되지 않았기 때문에 영속 객체는
#Persistence 상태를 유지할 수 있으며, 따라서 프록시 객체에 대한 Lazy Loading을 수행할 수 있게 된다
#버전 2.0부터 스프링 부트는 기본적으로 OSIV가 활성화되어 있을때 경고를 발생하므로 프로덕션 시스템에
#영향을 주기 전에 이 문제를 발견할 수 있다
#서블릿 필터에서 Session을 오픈하고 트랜잭션을 시작하던 전통적인 방식의 OPEN SESSION IN VIEW 패턴과 달리
#SpringMVC에서 제공하는 OpenSessionInViewFilter 는 필터 내에서 Session은 오픈하지만 
#트랜잭션은 시작하지 않는다. 따라서 서블릿 필터 안에서는 커넥션 풀로부터 JDBC커넥션을 얻을 필요가 없다
#https://getinthere.tistory.com/27 참고하세요
  jpa:
    open-in-view: true
    hibernate:
      ddl-auto: update #create로하면 model추가시 테이블 자동생성됨. 매번생성되니 테이블생성되면 update로 바꿀것
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      use-new-id-generator-mappings: false
    show-sql: true
    properties:
      hibernate.format_sql: true
      
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: 구글API아이디
            client-secret: 비번
            scope:
            - email
            - profile

 

Application.yml에 키값 넣어준다.

package com.example.demo.oauth;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;

@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
	//상속을 받았다는 건 제약사항이 생긴다는 의미... 오버라이딩을 해야할수도..
	//그냥 바로 source -> override method로 추가해주자!

	Logger log = LogManager.getLogger(PrincipalOauth2UserService.class);
	
	//구글로부터 받은 user에 대한 request 데이터에 대한 후처리 메소드 구현 - Profile정보 수집
	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		log.info("userRequest: " + userRequest);
		//엑세스 토큰 출력해보기
		log.info("구글에서 발급하는 토큰값 : " + userRequest.getAccessToken().getTokenValue());
		log.info("구글에서 발급하는 ID값 : " + userRequest.getClientRegistration().getRegistrationId());
		return super.loadUser(userRequest);
	}

}
package com.example.demo.auth;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.example.demo.model.User;
import com.example.demo.repository.UserRepository;

@Service
public class PrincipalDetailsService implements UserDetailsService {
	Logger log = LogManager.getLogger(PrincipalDetailsService.class);

	@Autowired
	private UserRepository userRepository;
	
	//아래 파라미터 username은 화면에서 사용하는 즉 input type의 name과 반드시 일치
	// -> /login 요청되면 시큐리티 인터셉트해서 자동으로 진행되는 부분
	//만일 다르게 하려면 SecurityConfig에서 .usernameParameter("mem_name")추가할 것 //mem_name 컬럼 살리려면 얘를 추가해줄것
	//loadUserByUsername메소드의 리턴은 어디로 가는가?
	//시큐리티 session(Authentication(내부의 UserDetails))로 담아줘야한다고...//무조건 userDetail타입이어야 담긴다고...
	//메소드 종료시 @AuthenticationPrincipal 어노테이션 생성됨
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		log.info(username);//사용자가 입력한 이름
		//JPA query method로 검색하기 - mysql
		User userEntity = userRepository.findByUsername(username);//검색하기
		log.info(userEntity);
		log.info(userEntity.getRole());
		if(userEntity != null) return new PrincipalDetails(userEntity);
		return null;
	}

}

 

프로젝트시간

프론트를 빨리 완성해야ㅠㅠ

댓글