{"componentChunkName":"component---src-templates-post-template-jsx","path":"/works/posts/2020-10-20--001","result":{"data":{"site":{"siteMetadata":{"title":"Blog by Eunyoung","subtitle":"작업 기록 블로그","copyright":"© All rights reserved.","author":{"name":"EunYoung","twitter":"#"},"disqusShortname":"","url":"https://ssongey.github.io"}},"markdownRemark":{"id":"43ca1f60-31ec-5fce-8cee-3d7b85e18af9","html":"<h3>의문사항</h3>\n<ul>\n<li>같은 Session 에서 중복 로그인이 가능하다.</li>\n<li>같은 Session 에서 중복 로그인 시 session id가 변경된다.</li>\n<li>로그아웃 후에 다시 로그인을 하면 ‘이미 접속된 아이디’ 오류가 난다.</li>\n<li>session 사용시 cookie 에 저장되는 JSESSIONID 에 대한 보안 이슈가 없는가</li>\n</ul>\n<h4>1. session 설정 내용</h4>\n<ul>\n<li>maximumSessions : 최대 세션 개수</li>\n<li>maxSessionsPreventsLogin : 기존에 접속한 사용자가 있을 경우 기존 사용자의 접속을 끊고, 나중에 접속한 사용자가 접속되도록 한다.(default: false)</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@EnableWebSecurity</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">SecurityConfig</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">WebSecurityConfigurerAdapter</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token annotation punctuation\">@Override</span>\n      <span class=\"token keyword\">protected</span> <span class=\"token keyword\">void</span> <span class=\"token function\">configure</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">HttpSecurity</span> http<span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">Exception</span> <span class=\"token punctuation\">{</span>\n        http<span class=\"token punctuation\">.</span><span class=\"token function\">sessionManagement</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">.</span><span class=\"token function\">maximumSessions</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">.</span><span class=\"token function\">maxSessionsPreventsLogin</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">.</span><span class=\"token function\">sessionRegistry</span><span class=\"token punctuation\">(</span><span class=\"token function\">sessionRegistry</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h4>2. DEBUG</h4>\n<p>chrome 에서 admin 계정으로 로그인 후(SessionId를 부여 받음) 새탭에서 다시 admin 계정으로 로그인을 하면 </p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/d0fa6/001-01.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 69.58333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABJ0AAASdAHeZh94AAABp0lEQVQ4y4VT21LrMAzs75BYviduSMvAy3k7UIb//5ZFFyeFUoaHHSkae7XWKofldEKbKpZWcV6PjIZ1XXFcHjG3RZHrhFwqUi4af8eEQ5kaQgioOaO1IxM0THNDZRQ+UBmZiWJK8D4wPIjh+Y4gKCJCjPp9SGUGkePLWUnqNCsSExTpyjEFJiGCcw7jOCokv4XUD7nO8Hy4sMJSTY0olOfFmLizQQiN1LA1ELVbncgboRRz9F1+6M/zdqETSfdhGH7gtm4K+XKMQRVRJ7o9vD31L5hClpoCqbpN2fDwcFfRnwoLG6Aul6JzS+k6S8kTKxcHdZ7aMOxu+83tLed6fzKbwoSliqtRHZZVkEOBN8D3OdIdZ3dzyPJuSmAlCW1Z0Y6PvDZNlzmmgpCKxsiKiZs4PusoYHSewWRkcRidwgiXfwjnV5TnC+LzxxUvH/BP73DnN9DTRXPPkc4X/bbaBe70hnH9r7Anc2fprg6TYaSrgr2mSr5Da86iYF8b3T8dvkHmarPbdlH+hO7sV4zDnT3c/8VoZnQ35Q/xJMZEjfuadGy79zX/BGGFs8k7goL5AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"001 01\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/d9199/001-01.png\"\n        srcset=\"/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/8ff5a/001-01.png 240w,\n/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/e85cb/001-01.png 480w,\n/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/d9199/001-01.png 960w,\n/devHistoryBlog/static/e71d8d22b54e9a89669134ce90d302ed/d0fa6/001-01.png 1263w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>동일한 SessionId 에서 로그인 시도를 했기 때문에<br>\nConcurrentSessionControlAuthenticationStrategy.onAuthentication() 에서\n123라인의 allowableSessionsExceeded() 메소드(중복로그인 exception)를 호출하지 않고 종료가 된다.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/c697d99ae775c93e05f8c47ffa869909/d4c13/001-02.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 825px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 55.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABJ0AAASdAHeZh94AAABbUlEQVQoz41SWXaDMAzkOGHxJm9gSEhee/8rTWUR0hA+2o95kjEazUhu1u8vPB43PO4L1nXGfd3iepv5+xWlZKRxQp5mRvkTDYUE6zyUUtDawBiLYRjQdR36vhfU/L9oLAVoJtFawzknICJBzY0xclfje16btm37ItqbN46iEBprkTPbSxkxJolbHjdycoeG3nvJa4PqbnfSEBdYvrBaCZxR8E6DXFVsuHgrtNxwJ3wp1ZvqA6F/Ejo9IAXCmDzmKXEk5BQQ07ghV0wIrJpYXbXbtpeT7cb5yHYJaugRPKHkiLEsjCum+YpxWnC/rViXBVYN7MCyg8BuLKxxou44w52w7zA6hRIzpszPZWHCZRbE4FmZRypRxjL0igVoaGVOr6AhJrSWh8uzyCXJEiKTRl6Qj54RxGIdzcjk24JIZjqwq6rwHUzI8h3Jlh2rMGTl53qujQQfz0eW+FzGiXC3XKW3l/Y57DN+bX2ej/gBpUFY1GzVPb4AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"001 02\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/c697d99ae775c93e05f8c47ffa869909/d4c13/001-02.png\"\n        srcset=\"/devHistoryBlog/static/c697d99ae775c93e05f8c47ffa869909/8ff5a/001-02.png 240w,\n/devHistoryBlog/static/c697d99ae775c93e05f8c47ffa869909/e85cb/001-02.png 480w,\n/devHistoryBlog/static/c697d99ae775c93e05f8c47ffa869909/d4c13/001-02.png 825w\"\n        sizes=\"(max-width: 825px) 100vw, 825px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>CompositeSessionAuthenticationStrategy.onAuthentication() 에서\nfixation 기본값 인 migrateSession에 의해 AbstractSessionFixationProtectionStrategy 가 delegate 된다. (89라인)</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/d8817/001-03.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 64.58333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABJ0AAASdAHeZh94AAABz0lEQVQ4y3WS6W7bMBCE/TaNed+UHCsp0tRH2qIoerz/m0yHlOzKcPrjw5KUPdjdmc3L+Q2H4wGfX19wPh3w5XzA8XTEfnrCuNtj9zhhGEaUUhcG1Mp7HW6odX7fhFQRtEVWEmMqGEjxEUPI2MXMc0C1pn+PSiEoTRS8EPDb7cz1LLCJucJYC88/xRgRQoRzDt55OOthjO3fldZQFJJSQlBgzfqtd2isg2EHSop3fkzW90Xgf1wFnfcI7NBzxNZlwxjDrtiZNgu239ddXYQu501YRm5jRu4vpgwfZuFWY/DI0SFYhei4O1bZR28dy3vBtkPNPYWYMIw7OjZ2Mdt22ESdoYjsQq06ww6luhG7GXkWNL2DsUTGonRzcs5IcTaoGWO16HhD9Aco8YAtnRUNsVSyiSnB1o+wzz+QXn8jffqF/PqH9Sfs9A16+g4/vSE9HVBIJuH5K8J0gtvP+IV2ZocFhpmzkaPmR7i8gy972DTyvUK6Au0SiVCdxLfa3wzz+q/OzDnkyJaxSdxjiHaBRiSOy71pI1kVf8doKQGttnRc9LOUl3EfOldTWhya2xfaXtdVtpxegr3inRyW7nAzIdOQTi7zfVWbOeIu1Pc5/As0J5fJd0jQlwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"001 03\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/d9199/001-03.png\"\n        srcset=\"/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/8ff5a/001-03.png 240w,\n/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/e85cb/001-03.png 480w,\n/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/d9199/001-03.png 960w,\n/devHistoryBlog/static/fc4dfbbf00d74e99288cdb4ddde139d5/d8817/001-03.png 1238w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>AbstractSessionFixationProtectionStrategy.onAuthentication() 에서\nSession Fixation Attack 방지로 인해 NewSessionId가 생성된다.<br>\n즉, 동일 로그인ID ‘admin’ 으로 SessionId, NewSessionId 각 2개가 생성되었다.  </p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/8d7b0/001-04.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 27.083333333333332%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAABJ0AAASdAHeZh94AAAA4klEQVQY042Oa0+DMBiF+f+/SZ0YHfOLN5w3GIuZDFtuVToEBB5LE7N9Mr7J8zY9p+ekTryNEakgFQlfVcHYafqmotbKnkOrqT9zS1UKPvJ3VJbQ6JJup2hMptMFO5XavLPZbEi2b/hBjHufc/GiWawaZneS4+sE10/xnhReUOMuS05upfEyZn7G2YOynC4VRzfSZhwpBXkmeVwLG1qsWjzDfCoONFevreUy6pgb3zPa9M4LJxqjt+YTNefP2npOGIZEUYQqMv434x+wL5RSMhitN8vSD+Y+Mgx7fvVDvg+Y/B/e73haYs9DigAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"001 04\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/d9199/001-04.png\"\n        srcset=\"/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/8ff5a/001-04.png 240w,\n/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/e85cb/001-04.png 480w,\n/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/d9199/001-04.png 960w,\n/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/07a9c/001-04.png 1440w,\n/devHistoryBlog/static/7a9a20ac71cd934e3e0e3ffefb6b4d9c/8d7b0/001-04.png 1723w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>탬 1, 탭2 의 브라우저 cookie 에는 마지막으로 생성된 NewSessionId가 부여되며, 기존 SessionId를 해제를 하지 못한 상태로 Client 에서 사라지게 된다.<br>\n즉, NewSessionId로 로그아웃을 하더라도 ‘admin’ 계정에 대한 SessionId가 존재하므로 재 로그인 시 중복된 로그인 에러가 뜨게 된다.</p>\n<h4>3. 해결방안 : sessionFixation - none</h4>\n<ul>\n<li>Session Fixation Attack 방지<br>\n악의적인 사용자가 사이트에 접근하기 위한 세션을 만들고, 그 세션을 통해 다른 사용자로 로그인 하려고 하는 경우(예를 들어, 세션에 ID를 파라미터로 포함하여 전송하는 경우)\nSession fixation attack의 잠재적인 위험이 존재하게 된다.<br>\n스프링 시큐리티는 이러한 공격을 자동으로 막기 위하여 사용자 로그인 때마다 새로운 세션을 생성한다.<br>\n이러한 방지 기능이 필요하지 않거나, 다른 기능들과 충돌이 발생할 경우에는, <session-management>의 session-fixation-protection 속성값으로 동작을 제어할 수 있다.<br>\n속성은 다음과 같은 세가지 옵션값들을 가진다.  </li>\n<li>동일 세션에서 로그인이 재발생해도 동일한 session id를 갖도록 한다.</li>\n<li>동일 세션에서 중복 로그인 후 로그아웃하면 해당 로그인 id에 대한 세션이 해제가 되어 재 로그인이 가능하다.</li>\n<li>none 으로 설정 시 호출되는 Session Strategy Class</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/2615a5eb6d37fb817a32f1a0a35d9071/8efc2/001-05.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 828px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 55.41666666666667%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABJ0AAASdAHeZh94AAABRElEQVQoz5WSWXLDIBBEdR0JMeybHG9x+f5H6gwgO7ZlVyofrwCBehqmh+P1ivPljMv3EafTHvv9gsNhwfGwQ84BIWWmrOMjBTFvGYyL0C6geINgFLR1sLx2IcLw3Bjbad89dJtbEBHGccQ0TU90QesRtIDTBMkHhRCY5/k+PiJuI++9owkadkSKNtX+4oNgaA7JEJRnh0o2Zskupn7oWUh0qkBdvwpaz1c2/DZewe00i/HGXKvXn8ePTm6FNg61Da0R3khEq5EcN8dZpPLFXVsQuZu1GbemeC4Y1IhZdKcbwVgKfEwgvqLnLgcWLNEhRxYNXMiH1lmlNJTWbU5KfXzXIeaeK7uKpRiwlISSAjITY0QuCxJnLJXqOCOxa+drdOQmBYOx9Tq+HaiRkaQgJT0gf6G+rhkketlbWWPjm/p/Y/OOH+iGVTfcvb59AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"001 05\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/2615a5eb6d37fb817a32f1a0a35d9071/8efc2/001-05.png\"\n        srcset=\"/devHistoryBlog/static/2615a5eb6d37fb817a32f1a0a35d9071/8ff5a/001-05.png 240w,\n/devHistoryBlog/static/2615a5eb6d37fb817a32f1a0a35d9071/e85cb/001-05.png 480w,\n/devHistoryBlog/static/2615a5eb6d37fb817a32f1a0a35d9071/8efc2/001-05.png 828w\"\n        sizes=\"(max-width: 828px) 100vw, 828px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n     </p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token comment\">// migrateSession : 새로운 세션을 생성하고 기존의 세션 값들을 새 세션에 복사해준다. 기본값으로 설정되어 있다.</span>\n<span class=\"token comment\">// none : 아무것도 수행하지 않는다. 원래의 세션이 유지된다.</span>\n<span class=\"token comment\">// newSession : \"깨끗한\" 새로운 세션을 생성한다. 기존의 세션데이터는 복사하지 않는다.</span>\n\nhttp<span class=\"token punctuation\">.</span><span class=\"token function\">sessionManagement</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">sessionFixation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">none</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">maximumSessions</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">maxSessionsPreventsLogin</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">sessionRegistry</span><span class=\"token punctuation\">(</span><span class=\"token function\">sessionRegistry</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h4>4. JSESSIONID 는 안전한가?</h4>\n<ul>\n<li>기본적으로 HttpOnly 를 사용   </li>\n<li>HttpOnly는 Set-Cookie HTTP 응답 헤더에 포함 된 추가 플래그   </li>\n<li>쿠키를 생성 할 때 HttpOnly 플래그를 사용하면 보호 된 쿠키에 액세스하는 클라이언트 측 스크립트의 위험을 완화하는 데 도움이됩니다</li>\n<li>XSS ( 교차 사이트 스크립팅 ) 결함이 존재하고 사용자가이 결함을 악용하는 링크에 실수로 액세스하더라도 브라우저 (주로 Internet Explorer)는 쿠키를 제 3 자에게 공개하지 않는다.</li>\n</ul>","fields":{"tagSlugs":["/tags/spring-security/"],"slug":"/works/posts/2020-10-20--001"},"frontmatter":{"title":"[작업로그] 이중로그인 방지 (Spring Security)","tags":["SpringSecurity"],"date":"2020-10-20","description":""}}},"pageContext":{"slug":"/works/posts/2020-10-20--001"}},"staticQueryHashes":[]}