{"id":9333,"date":"2024-08-25T12:40:53","date_gmt":"2024-08-25T03:40:53","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9333"},"modified":"2024-09-01T22:08:04","modified_gmt":"2024-09-01T13:08:04","slug":"spring-security-%eb%a1%9c%ea%b7%b8%ec%9d%b8%ec%9d%b4-%eb%90%98%ea%b8%b0%ea%b9%8c%ec%a7%80","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9333","title":{"rendered":"Spring Security &#8211; Filter \ub97c \uc54c\uba74 \ubaa8\ub4e0\uac8c \ubcf4\uc778\ub2e4."},"content":{"rendered":"<h1>Spring Security &#8211; Filter \ub97c \uc54c\uba74 \ubaa8\ub4e0\uac8c \ubcf4\uc778\ub2e4.<\/h1>\n<p>Spring Security \uc5d0 \ub300\ud55c \ub514\ubc84\uae45\uc744 \uc704\ud574 \uc791\ub3d9\ubc29\uc2dd\uc744 \ucc3e\uc544 \ubcf4\uc558\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc18c\uc2a4\ucf54\ub4dc\ub294 <a href=\"https:\/\/github.com\/skyer9\/my-spring-security\">\uae43\ud5c8\ube0c<\/a> \uc5d0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\ud750\ub984\ub3c4<\/h2>\n<p><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/wp-content\/uploads\/2024\/08\/2024-09-01-01.png\"><img decoding=\"async\" src=\"https:\/\/www.skyer9.pe.kr\/wordpress\/wp-content\/uploads\/2024\/08\/2024-09-01-01.png\" alt=\"\" \/><\/a><\/p>\n<h2>AuthorizationFilter<\/h2>\n<pre><code class=\"language-java\">@Configuration\n@EnableWebSecurity\npublic class SecurityConfig {\n\n    @Bean\n    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {\n        http\n                .csrf(AbstractHttpConfigurer::disable)\n                .authorizeHttpRequests(authorize -&gt;\n                        authorize\n                                .requestMatchers(&quot;\/assets\/**&quot;, &quot;\/login&quot;, &quot;\/error&quot;).permitAll()\n                                .anyRequest().authenticated()\n                )\n                .formLogin(formLogin -&gt;\n                        formLogin\n                                .loginPage(&quot;\/login&quot;));\n\n        SecurityFilterChain chain = http.build();\n        List&lt;Filter&gt; filters = chain.getFilters();\n        for (Filter filter : filters) {\n            System.out.println(filter.getClass());\n        }\n\n        return chain;\n    }\n\n}<\/code><\/pre>\n<p>SecurityFilterChain \uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 \ubaa8\ub4e0 \ud544\ud130\ub97c \ucd9c\ub825\ud574 \ubcf4\uc558\uc2b5\ub2c8\ub2e4.<\/p>\n<p><code>http request<\/code> \uac00 \ub4e4\uc5b4\uc624\uba74 SecurityFilterChain \uc774 \uac00\uc9c0\uace0 \uc788\ub294 \ud544\ud130 \uc911 AnonymousAuthenticationFilter \uac00 \ud638\ucd9c\ub418\uace0 login \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">.......session.DisableEncodeUrlFilter\n.......context.request.async.WebAsyncManagerIntegrationFilter\n.......context.SecurityContextHolderFilter\n.......header.HeaderWriterFilter\n.......authentication.logout.LogoutFilter\n.......authentication.UsernamePasswordAuthenticationFilter\n.......savedrequest.RequestCacheAwareFilter\n.......servletapi.SecurityContextHolderAwareRequestFilter\n.......authentication.AnonymousAuthenticationFilter\n.......access.ExceptionTranslationFilter\n.......access.intercept.AuthorizationFilter<\/code><\/pre>\n<p>login \ud398\uc774\uc9c0\uc5d0\uc11c \uc544\uc774\ub514\/\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 UsernamePasswordAuthenticationFilter \uc640 DaoAuthenticationProvider \uac00 \ud638\ucd9c\ub429\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">2024-09-01T11:45:01.880+09:00 DEBUG 22420 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing POST \/login\n2024-09-01T11:45:02.080+09:00 DEBUG 22420 --- [nio-8080-exec-3] o.s.s.a.dao.DaoAuthenticationProvider    : Authenticated user\n2024-09-01T11:45:02.135+09:00 DEBUG 22420 --- [nio-8080-exec-3] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@614d264d]\n2024-09-01T11:45:02.135+09:00 DEBUG 22420 --- [nio-8080-exec-3] w.a.UsernamePasswordAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]<\/code><\/pre>\n<p>\ub85c\uadf8\uc778 \uc774\ud6c4\uc5d0\ub294 SecurityContextHolderFilter \uc5d0\uc11c SecurityContext \uc18d Authentication \uc744 \ud655\uc778\ud558\uace0 \uc811\uc18d\uc744 \ud5c8\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">2024-09-01T12:18:14.003+09:00 DEBUG 2232 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing GET \/\n2024-09-01T12:18:14.004+09:00 DEBUG 2232 --- [nio-8080-exec-3] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]]\n2024-09-01T12:18:14.004+09:00 DEBUG 2232 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Secured GET \/<\/code><\/pre>\n<h2>Custom UsernamePasswordAuthenticationFilter<\/h2>\n<p>UsernamePasswordAuthenticationFilter \ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5\ud574\uc11c filter \uc5d0\uc11c provider \uae4c\uc9c0 \ub118\uc5b4\uac00\ub294 \uacfc\uc815\uc744 \ub530\ub77c\uac00 \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">    @Bean\n    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {\n        http.addFilterBefore(\n                new CustomUsernamePasswordAuthenticationFilter(authenticationManager),\n                UsernamePasswordAuthenticationFilter.class\n        );\n        \/\/ ......\n    }<\/code><\/pre>\n<pre><code class=\"language-java\">public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {\n\n    public CustomUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {\n        super(authenticationManager);\n        setSecurityContextRepository(new HttpSessionSecurityContextRepository());\n    }\n\n    @Override\n    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {\n        Authentication authentication = super.attemptAuthentication(request, response);\n\n        CustomUserDetails user = (CustomUserDetails) authentication.getPrincipal();\n        if (user.getUsername().startsWith(&quot;test&quot;)) {\n            return new UsernamePasswordAuthenticationToken(\n                    user,\n                    null,\n                    Stream.of(&quot;ROLE_ADMIN&quot;, &quot;ROLE_USER&quot;)\n                            .map(authority -&gt; (GrantedAuthority) () -&gt; authority)\n                            .collect(Collectors.toList())\n            );\n        }\n\n        return authentication;\n    }\n}<\/code><\/pre>\n<h2>Custom DaoAuthenticationProvider<\/h2>\n<p>\ucf54\ub4dc\ub97c \ub2e8\uc21c\ud654 \ud558\uae30 \uc704\ud574 Repository \ub4f1\uc740 \uc0dd\ub7b5\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n<p>DaoAuthenticationProvider \ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud574\uc11c \ud2b9\uc218\ud55c \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br \/>\n(\uc5f0\ub839\uccb4\ud06c, \uad6d\uc801\uccb4\ud06c \ub4f1)<\/p>\n<pre><code class=\"language-java\">    @Bean\n    public AuthenticationProvider daoAuthenticationProvider(CustomUserDetailsService userDetailsService) {\n\n        CustomDaoAuthenticationProvider authenticationProvider = new CustomDaoAuthenticationProvider();\n        authenticationProvider.setUserDetailsService(userDetailsService);\n        authenticationProvider.setPasswordEncoder(passwordEncoder());\n\/\/        authenticationProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());\n\/\/        authenticationProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());\n\n        return authenticationProvider;\n    }\n\n    @Bean\n    public BCryptPasswordEncoder passwordEncoder() {\n        return new BCryptPasswordEncoder();\n    }<\/code><\/pre>\n<pre><code class=\"language-java\">public class CustomDaoAuthenticationProvider extends DaoAuthenticationProvider {\n    @Override\n    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {\n        super.additionalAuthenticationChecks(userDetails, authentication);\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Service\npublic class CustomUserDetailsService implements UserDetailsService {\n    @Override\n    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {\n        Collection&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;&gt;();\n        authorities.add((GrantedAuthority) () -&gt; &quot;ROLE_USER&quot;);\n\n        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();\n\n        return CustomUserDetails\n                .builder()\n                .username(username)\n                .password(passwordEncoder.encode(&quot;password&quot;))\n                .authorities(authorities)\n                .build();\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Getter\n@Setter\n@Builder\npublic class CustomUserDetails implements UserDetails, Serializable {\n\n    private String username;\n    private String password;\n\n    private Collection&lt;GrantedAuthority&gt; authorities;\n\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Spring Security &#8211; Filter \ub97c \uc54c\uba74 \ubaa8\ub4e0\uac8c \ubcf4\uc778\ub2e4. Spring Security \uc5d0 \ub300\ud55c \ub514\ubc84\uae45\uc744 \uc704\ud574 \uc791\ub3d9\ubc29\uc2dd\uc744 \ucc3e\uc544 \ubcf4\uc558\uc2b5\ub2c8\ub2e4. \uc18c\uc2a4\ucf54\ub4dc\ub294 \uae43\ud5c8\ube0c \uc5d0 \uc788\uc2b5\ub2c8\ub2e4. \ud750\ub984\ub3c4 AuthorizationFilter @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorize -&gt; authorize .requestMatchers(&quot;\/assets\/**&quot;, &quot;\/login&quot;, &quot;\/error&quot;).permitAll() .anyRequest().authenticated() ) .formLogin(formLogin -&gt; formLogin .loginPage(&quot;\/login&quot;)); SecurityFilterChain chain = http.build();\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9333\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[54],"tags":[],"class_list":["post-9333","post","type-post","status-publish","format-standard","hentry","category-spring-boot-3-0"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9333","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9333"}],"version-history":[{"count":17,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9333\/revisions"}],"predecessor-version":[{"id":9363,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9333\/revisions\/9363"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}