<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>_susan.log</title>
        <link>https://velog.io/</link>
        <description>열공하자!</description>
        <lastBuildDate>Thu, 23 Mar 2023 08:50:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>_susan.log</title>
            <url>https://velog.velcdn.com/images/_susan/profile/ae52483f-1ee3-4439-9bb0-7b193c13967a/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. _susan.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_susan" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[git 사용 정리]]></title>
            <link>https://velog.io/@_susan/git-%EC%82%AC%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@_susan/git-%EC%82%AC%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 23 Mar 2023 08:50:56 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>Git Bash 또는 인텔리제이 Terminal에서 명령어 입력</li>
<li>merge 상태 확인은 <a href="http://10.20.0.36/warmhilt/medinu/-/network/dev" title="graph">Repository/Graph</a> 또는 GitKraken 설치 후 모니터링 가능</li>
</ul>
</blockquote>
<hr>
<table>
<thead>
<tr>
<th>git 반영 기본 틀은 pull → (add) → commit → push</th>
</tr>
</thead>
</table>
<h3 id="1-dev">1. dev</h3>
<p>현재 branch가 dev에 있는지 확인 후,</p>
<p>Local dev에 있는 소스와 다르게 origin dev에 업로드 되어 있는 소스가 있다면 </p>
<p><code>git pull origin dev</code> 입력 : branch에 올라와 있는 소스를 Local에도 받아주는 작업 진행 </p>
<p><img src="uploads/7cc3827befdded19073266680da5a63e/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_160314.png" alt="화면_캡처_2023-03-21_160314"></p>
<p><em><del>conflict(충돌)또는 추가 소스 발생 시 하단 참조</del></em></p>
<p>dev branch에서 Local과 branch가 함께 마지막 소스에 포인트 찍혀있는 것 확인 후 qa로 branch변경</p>
<p><img src="uploads/48bbb739cec643251e9f7128dbf66f64/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_145059.png" alt="화면_캡처_2023-03-21_145059"></p>
<h3 id="2-qa">2. qa</h3>
<p><code>git checkout qa</code> 입력</p>
<p><img src="uploads/e14175397fa5c245666a9b843e7e5c80/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_162539.png" alt="화면_캡처_2023-03-21_162539"></p>
<p>현재 branch가 qa로 가있는지 확인하는 방법으로는 </p>
<blockquote>
<ol>
<li>gitKraken 에서 그래프 qa의 체크 위치로 확인
<img src="uploads/f86b34c010cf909ed4212da0416a305d/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_163042.png" alt="화면_캡처_2023-03-21_163042"></li>
<li>인텔리제이 하단 오른쪽에 branch위치로 확인
<img src="uploads/0b5fd52236759f21e4336c3dfb2d19f8/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_163244.png" alt="화면_캡처_2023-03-21_163244"></li>
</ol>
</blockquote>
<p><code>git status</code> 입력</p>
<p><em><del>conflict(충돌)또는 추가 소스 발생 시 하단 참조</del></em></p>
<p>현재 qa branch의 상태 확인 후 pull안되어있는 부분 pull 시킴</p>
<p><code>git pull</code> 입력(바뀐 부분이 없다면 패스해도 됨)</p>
<h5 id="이후-origin원격-dev를-local-qa로-반영">이후, origin(원격) dev를 Local qa로 반영</h5>
<p><code>git pull origin dev</code> 입력</p>
<p><img src="uploads/7ee73cedc7398dc670153365c0825866/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_152220.png" alt="화면_캡처_2023-03-21_152220"></p>
<p>그래프에서 확인했을 때 origin(원격) dev소스가 qa branch 로 Merge가 되면</p>
<p>Local의 qa에 dev 소스가 반영되었음을 확인할 수 있음</p>
<p><code>git status</code> 입력</p>
<p><em><del>conflict(충돌)또는 추가 소스 발생 시 하단 참조</del></em></p>
<p><code>git push origin qa</code> 입력</p>
<p><img src="uploads/e92973d0458361b1cdc67b90ed01d6ac/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_160314.png" alt="화면_캡처_2023-03-21_160314"></p>
<p><code>git status</code> 입력으로 상태 확인</p>
<p><img src="uploads/bc5816e1bdc69b86e070fb31b6783bca/%ED%99%94%EB%A9%B4_%EC%BA%A1%EC%B2%98_2023-03-21_173602.png" alt="화면_캡처_2023-03-21_173602"></p>
<p>정상적으로 반영 완료</p>
<h3 id="3-prod">3. prod</h3>
<blockquote>
<p>dev → qa 반영과 거의 동일</p>
</blockquote>
<p><code>git checkout prod</code> 입력</p>
<p><code>git pull origin qa</code> 입력</p>
<p><em><del>conflict(충돌)또는 추가 소스 발생 시 하단 참조</del></em></p>
<ul>
<li>충돌 해결</li>
<li>commit</li>
</ul>
<p><code>git push origin prod</code> 입력</p>
<hr>
<ul>
<li>qa와 dev 합치면서 충돌 소스가 있는 경우</li>
</ul>
<h3 id="1안충돌사항-수정-이후-반영">1안(충돌사항 수정 이후 반영)</h3>
<p><img src="uploads/5cad7e5da30262795f0e2ba8c2e91383/ffffff.webp" alt="ffffff"></p>
<blockquote>
<p>&lt;&lt;&lt; HEAD 아래 부분은 현재 브렌치의 코드이고</p>
</blockquote>
<blockquote>
<p>==== 이후, &gt;&gt;&gt;&gt; 이전 부분은 다른 브렌치의 충돌 코드임</p>
</blockquote>
<p>충돌이 발생한 코드 수정을 한 뒤에</p>
<p><code>git add .</code> 입력</p>
<p><code>git commit -m &quot;메세지&quot;</code></p>
<p> 변경사항 반영 확인 후 <code>git status</code> 입력 이후 push</p>
<h3 id="2안stash---책갈피-활용">2안(Stash - 책갈피 활용)</h3>
<blockquote>
<p>백업 및 책갈피 개념으로 사용 가능</p>
</blockquote>
<table>
<thead>
<tr>
<th></th>
<th>명령어</th>
<th>활용 상황</th>
</tr>
</thead>
<tbody><tr>
<td>HEAD 설정</td>
<td><code>git stash</code></td>
<td>새로운 stash(책갈피)를 스택에 만들어 하던 작업을 임시로 저장(최신 commit을 저장해줌)</td>
</tr>
<tr>
<td>stash 적용</td>
<td><code>git stash apply</code></td>
<td>stash에 저장했던 최근 작업을 다시 가져온다</td>
</tr>
<tr>
<td>stash 적용2</td>
<td><code>git stash apply [stash 이름]</code></td>
<td>stash 이름 에 해당하는 stash를 적용한다</td>
</tr>
<tr>
<td>stash 제거</td>
<td><code>git stash drop</code></td>
<td>남아있는 stash를 삭제</td>
</tr>
<tr>
<td>stash 적용과 동시에 삭제</td>
<td><code>git stash pop</code></td>
<td>코드를 브렌치에 적용함과 동시에 stash내역에서 삭제</td>
</tr>
</tbody></table>
<h3 id="-merge병합-conflict충돌발생-시-참고-명령어-">※ Merge(병합) conflict(충돌)발생 시 참고 명령어 ※</h3>
<table>
<thead>
<tr>
<th></th>
<th>명령어</th>
<th>실행 상황</th>
</tr>
</thead>
<tbody><tr>
<td>merge 취소</td>
<td><code>git merge --abort</code></td>
<td>merge(병합) 이전의 원 상태로 되돌리기</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[AOP 사용시 유의점]]></title>
            <link>https://velog.io/@_susan/AOP-%EC%82%AC%EC%9A%A9%EC%8B%9C-%EC%9C%A0%EC%9D%98%EC%A0%90</link>
            <guid>https://velog.io/@_susan/AOP-%EC%82%AC%EC%9A%A9%EC%8B%9C-%EC%9C%A0%EC%9D%98%EC%A0%90</guid>
            <pubDate>Thu, 29 Dec 2022 05:22:58 GMT</pubDate>
            <description><![CDATA[<p>@After나 @Before을 사용할때는 JoinPoint를 사용하여 Parameter를 잡아줘도 상관없지만</p>
<p>@Around를 사용시에는 ProceedingJoinPoint를 사용해줘야 오류가 나지 않음. </p>
<p>`public Object afterThrowingEmailFail(ProceedingJoinPoint joinPoint) throws Throwable {</p>
<p>Object proceed = joinPoint.proceed();</p>
<p>.
.
.</p>
<p>return proceed;
}
``</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring boot 에서 XSS Filter 적용하기]]></title>
            <link>https://velog.io/@_susan/Spring-boot-%EC%97%90%EC%84%9C-XSS-Filter-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@_susan/Spring-boot-%EC%97%90%EC%84%9C-XSS-Filter-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 28 Dec 2022 02:51:06 GMT</pubDate>
            <description><![CDATA[<p>Spring boot에서 xss적용되도록 필터를 작성해봤다</p>
<p>첫째로 StringEscapeUtils가 적용 될수 있도록 build.gradle에
<code>implementation &#39;org.apache.commons:commons-text:1.10.0&#39;</code>
라이브러리를 추가한다</p>
<p>HtmlCharacterEscapes 클래스를 추가한다</p>
<p>`
public class HtmlCharacterEscapes extends CharacterEscapes {</p>
<pre><code>private final int[] asciiEscapes;

public HtmlCharacterEscapes() {
    // 1. XSS 방지 처리할 특수 문자 지정
    asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
    asciiEscapes[&#39;&lt;&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;&gt;&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;\&quot;&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;(&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;)&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;#&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
    asciiEscapes[&#39;\&#39;&#39;] = CharacterEscapes.ESCAPE_CUSTOM;
}

@Override
public int[] getEscapeCodesForAscii() {
    return asciiEscapes;
}

@Override
public SerializableString getEscapeSequence(int ch) {
    return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
}</code></pre><p>}`</p>
<p>XSS 필터 클래스를 만든다</p>
<p>`@Component
public class XSSFilter implements Filter {</p>
<pre><code>public FilterConfig filterConfig;

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException, IOException {
    chain.doFilter(new XSSFilterWrapper((HttpServletRequest) request), response);
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
}

@Override
public void destroy() {
    this.filterConfig = null;
}</code></pre><p>}`</p>
<p>XSSFilter를 적용할 Wrapper클래스를 만든다</p>
<p>`public class XSSFilterWrapper extends HttpServletRequestWrapper {</p>
<pre><code>private byte[] rawData;

public XSSFilterWrapper(HttpServletRequest request) {
    super(request);
    try {
        InputStream inputStream = request.getInputStream();
        this.rawData = replaceXSS(IOUtils.toByteArray(inputStream));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// XSS replace
private byte[] replaceXSS(byte[] data) {
    String strData = new String(data);
    strData = strData.replaceAll(&quot;\\&lt;&quot;, &quot;&amp;lt;&quot;).replaceAll(&quot;\\&gt;&quot;, &quot;&amp;gt;&quot;).replaceAll(&quot;\\(&quot;, &quot;&amp;#40;&quot;).replaceAll(&quot;\\)&quot;, &quot;&amp;#41;&quot;);

    return strData.getBytes();
}

private String replaceXSS(String value) {
    if(value != null) {
        value = value.replaceAll(&quot;\\&lt;&quot;, &quot;&amp;lt;&quot;).replaceAll(&quot;\\&gt;&quot;, &quot;&amp;gt;&quot;).replaceAll(&quot;\\(&quot;, &quot;&amp;#40;&quot;).replaceAll(&quot;\\)&quot;, &quot;&amp;#41;&quot;);
        value = value.replaceAll(&quot;\\&#39;&quot;, &quot;&amp;apos;&quot;);
        value = value.replaceAll(&quot;\&quot;&quot;, &quot;&amp;quot;&quot;);
        value = value.replaceAll(&quot;#&quot;, &quot;&amp;#35;&quot;);
        value = value.replaceAll(&quot;&amp;&quot;, &quot;&amp;amp;&quot;);
        value = value.replaceAll(&quot;eval\\((.*)\\)&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;[\&quot;\&#39;][\\s]*javascript:(.*)[\&quot;\&#39;]&quot;, &quot;\&quot;\&quot;&quot;);
        value = value.replaceAll(&quot;script&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;vbscript&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onreset&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmove&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onstop&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onrowsinserted&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;innerHTML&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;msgbox&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onstart&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onresize&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onrowexit&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onselect&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmousewheel&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondataavailable&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onafterprint&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onafterupdate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmousedown&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforeactivate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondatasetchanged&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforecopy&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforedeactivate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforeeditfocus&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforepaste&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforeprint&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforeunload&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforeupdate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onpropertychange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondatasetcomplete&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;oncellchange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onlayoutcomplete&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmousemove&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;oncontextmenu&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;oncontrolselect&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onreadystatechange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onselectionchange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onactivate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;oncopy&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;oncut&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onclick&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onchange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbeforecut&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondblclick&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondeactivate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondrag&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondragend&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondragenter&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondragleave&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondragover&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondragstart&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;ondrop&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onerror&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onerrorupdate&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onfilterchange&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onfinish&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onfocus&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onresizestart&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onunload&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onselectstart&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onfocusin&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onfocusout&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onhelp&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onkeydown&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onkeypress&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onkeyup&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onrowsdelete&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onload&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onlosecapture&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbounce&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmouseenter&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmouseleave&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onbefore&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmouseover&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmouseout&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmouseup&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onresizeend&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onabort&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmoveend&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onmovestart&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onrowenter&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onsubmit&quot;, &quot;&quot;);
        value = value.replaceAll(&quot;onblur&quot;, &quot;&quot;);
    }
    return value;
}

//새로운 인풋스트림을 리턴하지 않으면 에러가 남
@Override
public ServletInputStream getInputStream() throws IOException {
    if(this.rawData == null) {
        return super.getInputStream();
    }

    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.rawData);

    return new ServletInputStream() {

        @Override
        public int read() throws IOException {
            return byteArrayInputStream.read();
        }

        @Override
        public void setReadListener(ReadListener readListener) {

        }

        @Override
        public boolean isReady() {
            return false;
        }


        @Override
        public boolean isFinished() {
            return false;
        }
    };
}

@Override
public String getQueryString() {
    return replaceXSS(super.getQueryString());
}


@Override
public String getParameter(String name) {
    return replaceXSS(super.getParameter(name));
}


@Override
public Map&lt;String, String[]&gt; getParameterMap() {
    Map&lt;String, String[]&gt; params = super.getParameterMap();
    if(params != null) {
        params.forEach((key, value) -&gt; {
            for(int i=0; i&lt;value.length; i++) {
                value[i] = replaceXSS(value[i]);
            }
        });
    }
    return params;
}


@Override
public String[] getParameterValues(String name) {
    String[] params = super.getParameterValues(name);
    if(params != null) {
        for(int i=0; i&lt;params.length; i++) {
            params[i] = replaceXSS(params[i]);
        }
    }
    return params;
}


@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream(), &quot;UTF-8&quot;));
}


private static Pattern[] patterns = new Pattern[] {
        Pattern.compile(&quot;&lt;script&gt;(.*?)&lt;/script&gt;&quot;, Pattern.CASE_INSENSITIVE),
        Pattern.compile(&quot;src[\r\n]*=[\r\n]*\\\&#39;(.*?)\\\&#39;&quot;,
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile(&quot;src[\r\n]*=[\r\n]*\\\&quot;(.*?)\\\&quot;&quot;,
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile(&quot;&lt;/script&gt;&quot;, Pattern.CASE_INSENSITIVE),
        Pattern.compile(&quot;&lt;script(.*?)&gt;&quot;, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile(&quot;eval\\((.*?)\\)&quot;, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile(&quot;expression\\((.*?)\\)&quot;, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile(&quot;javascript:&quot;, Pattern.CASE_INSENSITIVE),
        Pattern.compile(&quot;vbscript:&quot;, Pattern.CASE_INSENSITIVE),
        Pattern.compile(&quot;onload(.*?)=&quot;, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
};

private String stripXSS(String value) {
    if (value != null) {

        value = value.replaceAll(&quot;\0&quot;, &quot;&quot;);

        for(Pattern scriptPattern : patterns){
            if(scriptPattern.matcher(value).matches()){
                value = value.replaceAll(&quot;&lt;&quot;, &quot;&amp;lt;&quot;).replaceAll(&quot;&gt;&quot;, &quot;&amp;gt;&quot;);
            }
        }
        value = value.replaceAll(&quot;&lt;&quot;, &quot;&amp;lt;&quot;).replaceAll(&quot;&gt;&quot;, &quot;&amp;gt;&quot;).replaceAll(&quot;&#39;&quot;,&quot;&amp;apos;&quot;);
    }
    return value;
}</code></pre><p>}`</p>
<p>고객사 보안규정에 따라 금지할 단어도 추가했는데.. 이부분이 적용되는지는 확인이 더 필요할듯하다
전반적으로는 &lt;,&gt;,(,),*,&amp;,/,&#39;,&quot; 이런 특수문자에만이라도 gt,lt 이런식으로 escape가 적용된다면 xss차단이 가능하다고 보인다.</p>
<p>이후 WebConfig 클래스에 Bean을 추가한다</p>
<p>`@Configuration
public class MedinaWebConfig implements WebMvcConfigurer {</p>
<pre><code>private final ObjectMapper objectMapper;

public MedinaWebConfig(ObjectMapper objectMapper) {
    this.objectMapper = objectMapper;
}

@Bean
public MappingJackson2HttpMessageConverter jsonEscapeConverter() {
    ObjectMapper copy = objectMapper.copy();
    copy.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
    return new MappingJackson2HttpMessageConverter(copy);
}

@Bean
public FilterRegistrationBean&lt;XSSFilter&gt; xssFilter() {
    FilterRegistrationBean&lt;XSSFilter&gt; filter = new FilterRegistrationBean&lt;&gt;();
    filter.setFilter(new XSSFilter());
    filter.addUrlPatterns(&quot;/*&quot;);
    return filter;
}</code></pre><p>}`</p>
<p>필터의 경로를 Bean으로 잡아주면 적용되는듯 함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AOP 참고했던 페이지]]></title>
            <link>https://velog.io/@_susan/AOP-%EC%B0%B8%EA%B3%A0%ED%96%88%EB%8D%98-%ED%8E%98%EC%9D%B4%EC%A7%80</link>
            <guid>https://velog.io/@_susan/AOP-%EC%B0%B8%EA%B3%A0%ED%96%88%EB%8D%98-%ED%8E%98%EC%9D%B4%EC%A7%80</guid>
            <pubDate>Wed, 21 Dec 2022 04:08:47 GMT</pubDate>
            <description><![CDATA[<p><a href="https://kogle.tistory.com/71">https://kogle.tistory.com/71</a> 참고</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[response 전체를 한 컬럼에 저장]]></title>
            <link>https://velog.io/@_susan/response-%EC%A0%84%EC%B2%B4%EB%A5%BC-%ED%95%9C-%EC%BB%AC%EB%9F%BC%EC%97%90-%EC%A0%80%EC%9E%A5</link>
            <guid>https://velog.io/@_susan/response-%EC%A0%84%EC%B2%B4%EB%A5%BC-%ED%95%9C-%EC%BB%AC%EB%9F%BC%EC%97%90-%EC%A0%80%EC%9E%A5</guid>
            <pubDate>Wed, 21 Dec 2022 02:42:16 GMT</pubDate>
            <description><![CDATA[<p>AOP를 사용해서 로그를 남기고 그 로그를 DB에 적재하는 업무중에 힘들어 하던 중
ToStringBuilder.reflectionToString
를 사용하면 response값을 String으로 변환해서 한 컬럼에 받을수 있다는 사실을 확인했다.
하지만 단점이.. UTF-8이 지원이 안된다는 부분때문에
다른방식을 선택</p>
<p> RsResponse rsResponse = (RsResponse) args;</p>
<pre><code>    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer());
    Gson gson = gsonBuilder.setPrettyPrinting().create();

    String json = gson.toJson(rsResponse.getResponse());
    JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();</code></pre><p>RsResponse로 받은 결과를 Object로 받아서
Json으로 변환하도록 하는방법!</p>
<p>gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer());
이부분은 타임이 &quot;year&quot; : &quot;2022&quot;, &quot;month&quot; : &quot;12&quot;, &quot;day&quot; : &quot;21&quot;, &quot;hour&quot; : &quot;11&quot;, &quot;minute&quot; : &quot;40&quot;, &quot;second&quot; : &quot;11&quot;, &quot;nano&quot;: &quot;23451230&quot; 이런식으로 나오는 형식 때문에
변환하는 방식!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java 구동 시간 체크]]></title>
            <link>https://velog.io/@_susan/Java-%EA%B5%AC%EB%8F%99-%EC%8B%9C%EA%B0%84-%EC%B2%B4%ED%81%AC</link>
            <guid>https://velog.io/@_susan/Java-%EA%B5%AC%EB%8F%99-%EC%8B%9C%EA%B0%84-%EC%B2%B4%ED%81%AC</guid>
            <pubDate>Fri, 02 Dec 2022 01:00:35 GMT</pubDate>
            <description><![CDATA[<pre><code>java

long number1startTime = System.currentTimeMillis();    //시간 선언
System.out.println(&quot;number1startTime = &quot; + number1startTime);    //1구간

long number2StartTime = System.currentTimeMillis();
        System.out.println(&quot;number2StartTime = &quot; + number2StartTime);    //2구간


long number3StartTime = System.currentTimeMillis();
        System.out.println(&quot;number3StartTime = &quot; + number3StartTime); //3구간

        .
        .
        .

        System.out.println(&quot; 총 소요시간 = &quot; + (number5StartTime - number1startTime));
            System.out.println(&quot;5구간 - 4구간 = &quot; + (number5StartTime - number4StartTime));
            System.out.println(&quot;4구간 - 3구간 = &quot; + (number4StartTime - number3StartTime));
            System.out.println(&quot;3구간 - 2구간 = &quot; + (number3StartTime - number2StartTime));
            System.out.println(&quot;2구간 - 1구간 = &quot; + (number2StartTime - number1startTime));

            //구간별로 소요시간 구할수 있음

            ```</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[단위테스트에서 Error.. NoSuchElementException]]></title>
            <link>https://velog.io/@_susan/%EB%8B%A8%EC%9C%84%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-Error..-NoSuchElementException</link>
            <guid>https://velog.io/@_susan/%EB%8B%A8%EC%9C%84%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-Error..-NoSuchElementException</guid>
            <pubDate>Thu, 13 Oct 2022 02:42:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>No value present
java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.get(Optional.java:148)</p>
</blockquote>
<p>Test코드를 작성하다가 나온 에러..
Table매핑을 하면서 Optional때문에 난 에러인듯 싶었다.</p>
<p>다른 Table에서 값을 가져오면서 Null값을 갖고올때의 조건처리를 안해줘서 났던 에러</p>
<blockquote>
<p>Optional null 처리
Optional<code>&lt;Menu&gt;</code> menu1 = Optional.empty();
        if(menu1.isPresent()) {
            final RsResponse response = target.addMenuToMenuTpl(MenuTplDto.MenuAddRequest.builder().build());
       }</p>
</blockquote>
<p>  이 조건을 추가해주면서 해결!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[나의 Error 기록]]></title>
            <link>https://velog.io/@_susan/%EB%82%98%EC%9D%98-Error-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@_susan/%EB%82%98%EC%9D%98-Error-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Thu, 13 Oct 2022 01:30:28 GMT</pubDate>
            <description><![CDATA[<p>Join을 진행한 테이블을 Mapping 테이블에 추가하는 코드에서,</p>
<pre><code>cannot deserialize from object value (no delegate- or property-based creator)</code></pre><p>이라는 에러가 발생했다.</p>
<p>검색결과,</p>
<p>jackson library가 빈 생성자가 없는 모델을 생성하는 방법을 모른다는 결과를 얻음..</p>
<p><strong>Solution</strong></p>
<p>Entity, 혹은 해당 데이터를 받는 Dto에 따로 빈 생성자를 추가해 주어야 함.</p>
<pre><code>//Getter, Setter는 생략
public class Member {
    private int id;
    private String username;
    private String password;
    private String email;

//기본 생성자 추가
public Member() {

}

public Member(int id, String username, String password, String email) {
    this.id = id;
    this.username = username;
    this.password = password;
    this.email = email;
}</code></pre><p>}</p>
]]></description>
        </item>
    </channel>
</rss>