본문 바로가기
코딩/수업 정리

21.02.22 [062] Mon

by 6^6 2021. 2. 22.
728x90

스프링 시큐리티

 

커스텀마이징하는것은 그냥 외울것.. 이해x 그냥 외우는것

 

 

MemberDetailsService.java

UserDetails의 정체

 

userHome.jsp에서 principal.emp.ename 이부분.

getEname한것임.

MemberUser.java 에서 MemberVO member; 해준것 --getMember을 호출하고있는것.

 

결국 세션을 갖다가 써야하는것임

userDetails는 memberuser를 갖고 온다. (=리턴한다는게 memberUser갖다쓴다는것)

userDetails을 세션에 정보 올려놔라. = getMember(MemberUser)를 메모리에 올려놔야한다는것 그래야 갖다 쓸 수 있음

--이래야 장바구니에 넣든 할수가 있음

 

userDetails = principal //결국 principal을 userDetails가 갖고있는것.

 

스프링시큐리티에서 세션 빨리하는 방법.

 

[UserController.java]

	// 세션을 어떻게 관리하는가.
	@GetMapping("/loginInfo")
	public String loginInfo(Principal principal) {// principle에 대한 객체

		// 1.Controller를 통하여 Pincipal객체로 가져오는 방법
		String user_id = principal.getName();
		System.out.println("유저 아이디:" + user_id);

		// 2.SpringContextHolder를 통하여 가져오는 방법(일반적인 빈에서 사용 할수있음 )
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		user_id = auth.getName();
		System.out.println("유저 아이디:" + user_id);

		// 3.
		UserDetails userDetails = (UserDetails) auth.getPrincipal();
		System.out.println(userDetails.getUsername());

		// 4. --핵심
		MemberUser memberUser = (MemberUser) auth.getPrincipal();
		System.out.println(memberUser.getPassword());

		// 4.User 클래스로 변환 하여 가져오는 방법
		User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		user_id = user.getUsername();
		System.out.println("유저 아이디:" + user_id);

		return "home";
	}
}

 

3. Principal은 부모. UserDetails는 자식 --다형성

 

4. userDetails는 Member가지고 있음. member가 갖고있는 password 가져옴.

principle이 userDetails(상속관계)다 갖고있음

★Userdetails(=principle) ⊃ user ⊃ memberUser★

 

**principel에는 getPrincipal, get...어쩌구 다 갖고있음....(...?)

 

 

 

 

==============

면접에 묻는 요즘 대세

★CSRF★- POST방식에서만 적용이된다. (두가지방법. 1.form, 2.ajax) --프로젝트에 반드시 써야함

스프링시큐리티에서 CSRF적용시키기

 

onebyone1.tistory.com/77,onebyone1.tistory.com/79

 

(XSS

동일출처원칙) --나중에함

 

 

=================

CSRF를 스프링시큐리티에 적용시키기

[security-db-context.xml]
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
	xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

//↓CSRF 이부분 수정
	<http>
	<csrf disabled="false"/>
	<!-- csrf를 적용하겠다. //↔ <csrf disabled="false"/>=csrf를 적용하지 않겠다는 뜻. 디폴트로 false임 -->
		<intercept-url pattern="/login/loginForm" access="permitAll" />
		<intercept-url pattern="/" access="permitAll" />
		<intercept-url pattern="/user/**" access="permitAll" />
		<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
		<intercept-url pattern="/**" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />

		<!-- 로그인 페이지 커스텀화 -->
		<form-login login-page="/login/loginForm"
			default-target-url="/"
			authentication-failure-url="/login/loginForm?error"
			username-parameter="id" password-parameter="password" />

		<logout logout-url="/logout" logout-success-url="/" />

		<!-- 403 에러 처리 -->
		<access-denied-handler
			error-page="/login/accessDenied" />
	</http>

	<beans:bean id="userDetailsService"
		class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
		<beans:property name="dataSource" ref="dataSource" />
	</beans:bean>

	<!-- 여기추가 -->
	<beans:bean id="customNoOpPasswordEncoder"
		class="edu.bit.ex.security.CustomNoOpPasswordEncoder" />

	<!-- addUser할때 필요. 추가. -->
	<beans:bean id="bcryptPasswordEncoder"
		class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

	<!-- provider -->
	<authentication-manager>
		<authentication-provider>

			<!-- 여기추가 -->
			<password-encoder ref="bcryptPasswordEncoder" />
			<jdbc-user-service data-source-ref="dataSource"
				role-prefix=""
				users-by-username-query="select username, password, enabled from users where username = ?"
				authorities-by-username-query="select username, authority from authorities where username = ?" />
		</authentication-provider>
	</authentication-manager>
</beans:beans>
[loginForm2.jsp] - CSRF-1.form 방법
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<%@ include file="/WEB-INF/include/header.jspf"  %>
<title>Login</title>
</head>
<body onload="document.f.id.focus();">
      <br><br>
      <div class="container text-center">
          <h1>로그인 페이지</h1><br>
      </div>
      <c:url value="/login" var="loginUrl" />
      <div class="container col-md-4">
	      <form:form name ="f" class="px-4 py-3" action="${loginUrl}" method="post">
	            <c:if test="${param.error != null}">
        			<p>아이디와 비밀번호가 잘못되었습니다.</p>
    			</c:if>
    			
    			<c:if test="${param.logout != null}">
        			<p>로그아웃 하였습니다.</p>
    			</c:if>
    			
	          <div class="form-group">
	              <label for="exampleDropdownFormEmail1">ID</label>
	              <input type="text" class="form-control" name="id" placeholder="example">
	          </div>
	          <div class="form-group">
	              <label for="exampleDropdownFormPassword1">Password</label>
	              <input type="password" class="form-control" name="password" placeholder="Password">
	          </div>
	          <div class="form-check">
	              <label class="form-check-label">
	              <input type="checkbox" class="form-check-input">
	              Remember me
	              </label>
	          </div>
              
              //↓요부분
<%-- 	  <input name="${_csrf.parameterName}" type="hidden" value="${_csrf.token}"/> --%>
	          <button type="submit" class="btn btn-primary">Sign in</button>
	   </form:form>
	      <div class="dropdown-divider"></div>
	      <a class="dropdown-item" href="#">New around here? Sign up</a>
	      <a class="dropdown-item" href="#">Forgot password?</a>
	  </div>

</body>
</html>

**<form:form name="f" action="${loginUrl}" method="POST">

//<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> 

</form:form>

을 적어주면 안에 저부분이 그냥 자동으로 들어간다.

 

**<form> 폼태그만 적어주게되면 주석 풀어야함!!

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> 

</form>

 

따라서 주석을 처리했음에도 불구하고 token이 나타난다.(value="_csrf.token")

 

 

 

 

CSRF공격이란?

CSRF 공격(Cross Site Request Forgery)

 

 

CSRF 방어

1.Referer 체크

 

2. 토큰 발급

로그인한 유저에 대해 매번 새로운 토큰을 발급함(스프링 시큐리티가 발급해줌)으로써, 서버에 요청을 보낼 때는 항상 해당 토큰을 함께 전송해야만 이에 대한 응답을 하는 방법.(=패스워드를 하나 더준다.)

 

↓CAPTCHA 임

 

 

 

2.ajax로 보내는 방법 ↓이블로그 참고

hyunsangwon93.tistory.com/28

 

Spring Boot CSRF AJAX 전송 방법

CSRF ? 사이트 간 요청 위조(또는 크로스 사이트 요청 위조, 영어: Cross-site request forgery, CSRF, XSRF)는 웹사이트 취약점 공격의 하나로, 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행

hyunsangwon93.tistory.com

CSRF-2.ajax 방법
<script type="text/javascript">

	$(function() {
		$("#ajaxCall").click(function(){
			ajaxCall();
		});
	});
	
	function ajaxCall(){
		var token = $("meta[name='_csrf']").attr("content");
		var header = $("meta[name='_csrf_header']").attr("content");
		var name = $("#userName").val();
		
		var jsonData = {
			"name" : name
		}
		
		$.ajax({
			type: 'POST',
			contentType: "application/json",
			url:'/csrf/ajax',
			data: JSON.stringify(jsonData), // String -> json 형태로 변환
			beforeSend : function(xhr)
            {   /*데이터를 전송하기 전에 헤더에 csrf값을 설정한다*/
				xhr.setRequestHeader(header, token);
            },
			dataType: 'json', // success 시 받아올 데이터 형
			async: true, //동기, 비동기 여부
			cache :false, // 캐시 여부
			success: function(data){
				console.log(data.name);
			},
			error:function(xhr,status,error){
				console.log('error:'+error);
			}
		});
	}
	
</script>

 

 

 

 

csrf의 의미

스프링시큐리티에서의 의미

 

 

 

-XSS

-동일출처원칙

sql injextion($,#)

 

해킹:admin 계정 탈취

해당 시스템 버전 정보(서버 리눅스)

 

 

 

============================================================================

============================================================================

소셜 로그인 - 인증과 권한 리소스

1.구글, 페이스북 : 스프링에서 라이브러리(Oauth2)

2.직접구현 - 카카오로그인(공식사이트에서 공식문서에 들어가 하라는대로 하면됨)

일단 이거는 기본으로 읽고 시작해야한다.

developers.kakao.com/docs/latest/ko/kakaologin/rest-api

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 


Oauth2란?

카카오가 왔다리갔다리를 구현한것.

유저가 url을 카카오에게 준다.

유저가 카카오를 클릭하게되면 카카오가 로그인을 하라고 하면서 통신이 시작된다.

(카카오에게 인증과 권한을 맡기는것)

 

 

 

json을 자바객체로 만들어줘야함. 그게 Gson임

 

 

 

kakaoProfile, properties 이렇게 클래스 두개 만들기

근데(리팩토링에 쓰기--ppt에 억지로라도 만들기)

public class kakaoProfile{

변수1, 변수2... ;

   public class Properties{

//이렇게 클래스안에 클래스는 넣으면안됨--서버에서 이렇게 넣으면 매우매우 큰 실수를 하는것.

  }

}

--why? inner파일은 상호참조를 하고있기때문에 메모리에서 끝까지 회재?가 안된다.

우리가 하고있는 프로그래밍은 서버인데 저렇게 이너클래스를 만들게되면 몇십만명의 것이 메모리에서 쌓여서 서버 죽고 빠빠이 된다.

해결방법은 public static class Properties{} 이렇게 static을 붙여주던지 아님 그냥 클래스를 따로 떼서 만든다.

--그냥 inner class 금지! 라고 생각하기

** 이펙티드 자바 책 필수--여기에서도 저 내용이 나온다.(22장(구버전),24장(신버전))

 

 

 

 

 

 

 

 

 

 

 

728x90

'코딩 > 수업 정리' 카테고리의 다른 글

21.02.24 [064] Wed  (0) 2021.02.24
21.02.23 [063] Tue  (0) 2021.02.23
21.02.19 [061] Fri  (0) 2021.02.19
21.02.18 [060] Thu  (0) 2021.02.18
21.02.17 [059] Wed  (0) 2021.02.17

댓글