부트스트랩에서 페이징 인터페이스 가져오기

 

 

home.jsp에 넣기

 

 

중앙정렬하기

 

 

결과

 

 

BoardHomeAction

모두 가져 오는 것이 아니라 3개만 가져오기

 

 

변경된 모습

 

 

BoardRepository

 

 

결과

 

 

 

'Web > Jsp' 카테고리의 다른 글

첫페이지 끝페이지 이동버튼 비활성화  (0) 2020.06.10
상세보기시 조회수 증가  (0) 2020.06.09
JSP 서블릿 비밀번호 암호화  (0) 2020.06.09
유튜브 업로드 오류 잡기  (0) 2020.06.09
Jsoup HTML파싱 // 미리보기  (0) 2020.06.09

 

데이터 날리기

 

 

결과

 

// 해쉬암호 : 최근에는 대부분 SHA256을 사용한다.
// 해쉬는 복호화가 되지않는다.
// 암호화와 복호화가 되는 기술은 base64

// 해쉬와 해쉬를 비교하여 검증
// 해쉬는 고정길이라서 같은 값이 나올 수 있다 (충돌)
// 뚫릴 수 있다

// 레인보우 테이블

// 소금치기

 

UsersJoinProcAction

 

 

SHA256

 

테스트코드

더보기
package com.cos.blog.test;

import java.security.MessageDigest;

import org.junit.Test;

//해쉬암호 : 최근에는 대부분 SHA256을 사용한다.
//해쉬는 복호화가 되지않는다.
//암호화와 복호화가 되는 기술은 base64

//해쉬와 해쉬를 비교하여 검증
//해쉬는 고정길이라서 같은 값이 나올 수 있다 (충돌)
//뚫릴 수 있다

//레인보우 테이블

//소금치기


public class SHA256Test {
	
	private final static String salt = "코스";
	
	@Test
	public void encSha256() {
		
		String plain = "1234";
		String result = "";
		
		byte[] bytePlain = plain.getBytes(); // 들어온 문자들을 바이트 단위로 쪼갠다.
		
		for (byte b : bytePlain) {
			System.out.println(b);
		}
		
		byte[] bytesalt = salt.getBytes();
		
		for (byte b : bytesalt) {
			
			System.out.println(b);
		}
		
		
		byte[] bytePlainAndSalt = new byte[bytePlain.length + bytesalt.length];
		
		for (int i = 0; i < bytePlainAndSalt.length; i++) { // 비밀번호와 솔트 넣기
			
			if(i < bytePlain.length) { // 바이트 플레인 길이만큼 채워넣고
				
				bytePlainAndSalt[i] = bytePlain[i];
				
			} else { // 플레인 길이를 오버하면 그 뒤에 솔트를 채워넣는다.
				
				// i - bytePlain.length은 예를들어 i가 6이면 6-6이 되어서 0번째 배열 내용을 소환한다.
				bytePlainAndSalt[i] = bytesalt[i - bytePlain.length];
				
			}
			
		}
		
		
		System.arraycopy(bytePlain, 0, bytePlainAndSalt, 0, bytePlain.length);
		// 매개변수 ; 첫번째 넣을배열, 두번째 넣을배열 시작위치, 세번째 받을배열, 네번째 받을배열 시작위치, 다섯번째 넣을길이
		
		System.arraycopy(bytesalt, 0, bytePlainAndSalt, bytePlain.length, bytesalt.length);
		
		
		for (byte b : bytePlainAndSalt) {
			
			System.out.print(b + " ");
			
		}
		
		try {
			
			MessageDigest md = MessageDigest.getInstance("SHA-256"); // SHA-256암호화 객체 생성
			md.update(bytePlainAndSalt); // md 객체 안에 세팅
			
			byte[] bytedata = md.digest(); // md 객체에서 데이터 받아오기
			
			// StringBuffer 동기화 기능이 있어서 여러 객체가 접근하지 못한다. 임계구역
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < bytedata.length; i++) {
				sb.append(Integer.toHexString((bytedata[i] & 0xFF) + 256).substring(1));
			}
			
			System.out.println(sb.toString());
			
			
			
		} catch (Exception e) {
			
		}
		
		
	}
}

 

 

결과

 

 

 

 

 

 

 

 

 

 

유튜브 업로드 오류 잡기

 

 

링크를 걸고 엔터친 뒤 다시 링크를 걸면 링크가 3개가 된다

 

링크 이름이 공백이 아니면 동영상을 출력한다

 

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

 

 

 

Jsoup.parse(content);

를 이용하면

content의 내용을 아래와 같이 html문자열로 파싱해준다.

 

 

Elements pTags = doc.select("p");

파싱된 HTML문자열에서 p태그들을 찾아서 Elements라는 배열에 넣는다.

 

pTags.get(0).text()

p태그들 중에서 0번째 태그 + 내용

(태그 안의 값을 가져오려면 .val()을 이용한다)

 

 

경로는 무조건 절대경로

 

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

a태그를 이용한 자바스크립트 사용

detail.jsp

a 태그에서 자바스크립트를 이용하려면 href에 javascript: 을 이용한다.

 

위 코드의 결과물 (부트 스트랩)

 

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

상세보기

Jsoup : HTML 파서

home.jsp

상세보기를 a태그로 만들어보자

EL표현식으로 보드의 id를 주소값에 넣어주자

 

 

오라클 디벨로퍼에서 조인 쿼리문을 제작

 

 

BoardRepository

BoardRepository에서 해당 쿼리문을 입력한다. (스트링빌더)

스트링 빌더를 이용할 경우에 쿼리문 맨 뒤쪽에 공백을 하나 꼭 주자 (안그러면 문자열이 붙어버린다. usernameFROM)

 

 

DetailResponseDto

상세보기에는 보드내용과 같이 작성자 유저네임이 필요하기 때문에

DTO를 제작하여 데이터를 합쳐서 보낸다. 중요!

서버에서 객체를 여러개 생성해서 response를 하면 여러번 보내야 하기 때문에 하나만 보낼 수 있게 객체를 생성하는 것이 좋다.

서버 내부에서의 통신에서는 굳이 안만들어도 무방하다.

 

 

detail.jsp

EL표기식으로 데이터를 입력해준다.

 

 

부트스트랩에서 클래스를 이용한 색깔 조정 가능

 

 

결과

 

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

페이지 수정하기

수정버튼을 a태그로 만들어 보자

a태그는 get방식을 사용할 때만 쓰자

 

 

BoardUpdateAction

 

 

update.jsp

writeSummer.jsp를 복사하여 붙여넣고, EL코드들을 추가한다.
기존 내용을 받아와서 넣는 작업이다.

 

 

BoardUpdateProcAction

유효성 체크에 id를 넣어준다.

 

 

BoardRepository

보드아이디로 검색하여 제목과 내용을 업데이트한다.

 

 

BoardUpdateProcAction

등록 성공시 보드아이디를 이용해서 해당페이지로 다시이동한다.

 

 

결과

 

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

삭제하기

 

detail.jsp

삭제버튼에 onclick을 넣어주고 함수를 만들어주자

 

delete 컨트롤러로 보내는 ajax

주소값이 노출되도 되지만 delete는 get방식으로 사용하지 않는다. post를 이용하자.

 

 

BoardController

라우터에 delete를 추가

 

 

BoardDeleteAction

 

BoardRepository

 

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

 

ajax용 리턴함수를 만들어주자

 

 

UsersUsernameCheckAction

ajax는 문자열 등의 데이터를 받기 때문에 printWriter 등의 버퍼드라이터 종류를 사용한다.

 

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

 

로그인시 쿠키 있으면 미리 체크 해두기

간단하게 JSTL조건문을 사용하여 쿠키가 없다면 체크해제 있다면 체크

 

 

결과

 

 

Youtube 파싱

첫번째 방식

디테일 액션 파일에서 Jsoup를 이용하여 a태그를 찾고, 태그가 있다면 href주소를 파싱하여 재생화면을 보여준다.

유튜브 주소는 여러가지 종류가 있으니 각각 처리해주자.

 

 

결과

 

두번째 방식

 

 

HtmlParser.java

 

 

회원정보 업데이트

UsersController

컨트롤러에 회원정보 업데이트 분기

 

 

BoardUpdateAction

아이디가 없거나 잘못된 아이디로 접근할 경우 메시지

 

 

BoardUpdateProcAction

수정을 시도하면 세션에 아이디가 있는지 체크

 

 

update.jsp

회원정보 수정 화면

 

 

유저이름은 읽기전용으로 변경

 

 

 

자바에서 HTML 파싱

 

jsoup jar 다운로드 

 

html 태그들을 자바 오브젝트로 변환한다

 

예제1

 

예제2

 

web.xml 필터 임시적으로 해제

 

HtmlParser 만들기

 

 

 

 

 

 

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

XSS 쿠키 하이재킹

XSS

자바스크립트를 페이지에 집어넣어서 공격

쿠키 하이재킹

쿠키는 사이트마다 다른 값을 가지고 있음, getCookie하면 쿠키값을 얻어올 수 있다.
이것을 방지하기 위해 스크립트 공격 못하도록 막으면 홈페이지의 디자인도 망가질 수 있다.

 

-----

xss공격 수동으로 

 

 

HttpOnly를 쓰지않은 경우

 

HttpOnly를 사용한 경우

 

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

 

자바스크립트 공격을 막기 위해

getter를 이용해서 파싱

 

 

 

1. 코드를 이용해서 개별적으로 막는방법

 

http://naver.github.io/lucy-xss-filter/kr/#_xsspreventer_2

 

Lucy XSS Filter

XSS 공격이 가능한 HTML 요소를 신뢰할 수 있는 코드로 변환하거나 삭제하는 기능을 제공한다. 공격이 가능하지 않은 HTML 요소는 허용을 한다. 4.1. 설정 파일 Lucy-XSS Filter의 필터링 규칙은 화이트리

naver.github.io

 

 

의존하는 파일들도 다운

 

라이브러리 추가

 

코드 테스트

 

결과

 

 

2. xml파일을 이용해서 서버 전체에 xss막기

 

https://github.com/naver/lucy-xss-servlet-filter

 

naver/lucy-xss-servlet-filter

Contribute to naver/lucy-xss-servlet-filter development by creating an account on GitHub.

github.com

 

라이브러리 다운

 

의존하는 파일도 추가

 

 

web.xml 에 해당 코드 넣기

더보기
	<filter>
		<filter-name>xssEscapeServletFilter</filter-name>
		<filter-class>com.navercorp.lucy.security.xss.servletfilter.XssEscapeServletFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>xssEscapeServletFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

필터는 xml 파일 가장 아래에 입력한다. (인코딩이 모두 된 후의 문자를 필터링해야 되기 때문)

 

 

xssEscapeServletFilter가 모든 url 패턴을 가로채도록 만든다

필터를 커스터마이징 하려면

com.navercorp.lucy.security.xss.servletfilter.XssEscapeServletFilter 를 상속받아서

새 클래스를 만들고 그 내부에서 커스터마이징 해야한다.

하지만 그것이 번거롭기 때문에

아래와 같이  lucy-xss-servlet-filter-rule.xml 파일을 이용한다.

 

java src 루트에 lucy-xss-servlet-filter-rule.xml 파일생성

아래코드 입력

더보기
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.navercorp.com/lucy-xss-servlet">
   <defenders>
       <!-- XssPreventer 등록 -->
       <defender>
           <name>xssPreventerDefender</name>
           <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssPreventerDefender</class>
       </defender>

       <!-- XssSaxFilter 등록 -->
       <defender>
           <name>xssSaxFilterDefender</name>
           <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssSaxFilterDefender</class>
           <init-param>
               <param-value>lucy-xss-sax.xml</param-value>   <!-- lucy-xss-filter의 sax용 설정파일 -->
               <param-value>false</param-value>        <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
           </init-param>
       </defender>

       <!-- XssFilter 등록 -->
       <defender>
           <name>xssFilterDefender</name>
           <class>com.navercorp.lucy.security.xss.servletfilter.defender.XssFilterDefender</class>
           <init-param>
               <param-value>lucy-xss.xml</param-value>    <!-- lucy-xss-filter의 dom용 설정파일 -->
               <param-value>false</param-value>         <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
           </init-param>
       </defender>
   </defenders>

    <!-- default defender 선언, 별다른 defender 선언이 없으면 default defender를 사용해 필터링 한다. -->
    <default>
        <defender>xssPreventerDefender</defender>
    </default>

    <!-- global 필터링 룰 선언 -->
    <global>
        <!-- 모든 url에서 들어오는 globalParameter 파라메터는 필터링 되지 않으며 
                또한 globalPrefixParameter로 시작하는 파라메터도 필터링 되지 않는다. -->
        <params>
            <param name="globalParameter" useDefender="false" />
            <param name="globalPrefixParameter" usePrefix="true" useDefender="false" />
        </params>
    </global>

    <!-- url 별 필터링 룰 선언 -->
    <url-rule-set>
       
       <!-- url disable이 true이면 지정한 url 내의 모든 파라메터는 필터링 되지 않는다. -->
       <url-rule>
           <url disable="true">/disableUrl1.do</url>
       </url-rule>
       
        <!-- url1 내의 url1Parameter는 필터링 되지 않으며 또한 url1PrefixParameter로 시작하는 파라메터도 필터링 되지 않는다. -->
        <url-rule>
            <url>/url1.do</url>
            <params>
                <param name="url1Parameter" useDefender="false" />
                <param name="url1PrefixParameter" usePrefix="true" useDefender="false" />
            </params>
        </url-rule>
        
        <!-- url2 내의 url2Parameter1만 필터링 되지 않으며 url2Parameter2는 xssSaxFilterDefender를 사용해 필터링 한다.  -->
        <url-rule>
            <url>/url2.do</url>
            <params>
                <param name="url2Parameter1" useDefender="false" />
                <param name="url2Parameter2">
                    <defender>xssSaxFilterDefender</defender>
                </param>
            </params>
        </url-rule>
    </url-rule-set>
</config>

 

결과

 

추가설정을 하기 위해서는 lucy-xss-sax.xml 파일을 만들어서 설정해준다(미완)

 

 

 

https://ninearies.tistory.com/123

 

[Summernote] Summernote (썸머노트) 사용법

1. 썸머노트 다운로드 https://summernote.org/ Summernote - Super Simple WYSIWYG editor Super Simple WYSIWYG Editor on Bootstrap Summernote is a JavaScript library that helps you create WYSIWYG editor..

ninearies.tistory.com

 

 

 

 

 

 

더보기
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Summernote with Bootstrap 4</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

    <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>
  </head>
  <body>
    <div id="summernote"></div>
    <script>
      $('#summernote').summernote({
        placeholder: 'Hello Bootstrap 4',
        tabsize: 2,
        height: 100
      });
    </script>
  </body>
</html>

위 코드 중에서 필요한 것만 잘라서 사용

 

 

(div나 textarea에 넣을 수 있음)

 

 

테스트 결과

 

 

+ Recent posts