\ubcf4\uc548 \ubb38\uc81c\ub294 \ub300\ubd80\ubd84\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc911\uc694\ud55c \uc774\uc288\uc785\ub2c8\ub2e4. \uc2a4\ud504\ub9c1 \ud504\ub808\uc784\uc6cc\ud06c\ub294 \ubcf4\uc548 \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 \uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0(Spring Security)\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\ub294 \uc778\uc99d(Authentication)\uacfc \uad8c\ud55c \ubd80\uc5ec(Authorization)\ub97c \uc704\ud55c \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uba70, \ubcf4\uc548 \uac15\ud654\uc5d0 \ub9e4\uc6b0 \uc720\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n
\uc774\ubc88 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\ub97c \ud65c\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubcf4\uc548\uc744 \uac15\ud654\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\ub294 \uc778\uc99d(Authentication)\uacfc \uad8c\ud55c \ubd80\uc5ec(Authorization)\ub97c \uc704\ud55c \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc778\uc99d\uc740 \uc0ac\uc6a9\uc790\uac00 \uc790\uc2e0\uc774 \uc8fc\uc7a5\ud558\ub294 \ub300\ub85c \uc2e0\uc6d0\uc744 \uc99d\uba85\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud558\uba70, \uad8c\ud55c \ubd80\uc5ec\ub294 \uc778\uc99d\ub41c \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud574 \ud5c8\uac00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud569\ub2c8\ub2e4.<\/p>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c \uc778\uc99d\uc740 AuthenticationManager\uac00 \uc218\ud589\ud558\uba70, \uc778\uc99d \ubc29\ubc95\uc740 \ub2e4\uc591\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub0b4\ubd80 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc778\uc99d \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\uac70\ub098, LDAP, OAuth, OpenID \ub4f1\uc758 \uc678\ubd80 \uc778\uc99d \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
\uad8c\ud55c \ubd80\uc5ec\ub294 AccessDecisionManager\uac00 \uc218\ud589\ud558\uba70, \uad8c\ud55c \ubd80\uc5ec \ubc29\ubc95\uc740 Access Control List(ACL), Role-Based Access Control(RBAC), Expression-Based Access Control \ub4f1 \ub2e4\uc591\ud569\ub2c8\ub2e4.<\/p>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c \uc778\uc99d\uc740 AuthenticationManager\uac00 \uc218\ud589\ud569\ub2c8\ub2e4. \uc778\uc99d \ubc29\ubc95\uc740 AuthenticationProvider\ub97c \ud1b5\ud574 \ud655\uc7a5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub0b4\ubd80 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc778\uc99d \uc815\ubcf4\ub97c \uac80\uc99d\ud558\ub294 DaoAuthenticationProvider\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Autowired\n private UserDetailsService userDetailsService;\n\n @Bean\n public PasswordEncoder passwordEncoder() {\n return new BCryptPasswordEncoder();\n }\n\n @Override\n protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n auth.authenticationProvider(daoAuthenticationProvider());\n }\n\n @Bean\n public DaoAuthenticationProvider daoAuthenticationProvider() {\n DaoAuthenticationProvider provider = new DaoAuthenticationProvider();\n provider.setUserDetailsService(userDetailsService);\n provider.setPasswordEncoder(passwordEncoder());\n return provider;\n }\n}<\/code><\/pre>\n2. \uad8c\ud55c \ubd80\uc5ec(Authorization)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c \uad8c\ud55c \ubd80\uc5ec\ub294 AccessDecisionManager\uac00 \uc218\ud589\ud569\ub2c8\ub2e4. \uad8c\ud55c \ubd80\uc5ec \ubc29\ubc95\uc740 Access Control List(ACL), Role-Based Access Control(RBAC), Expression-Based Access Control \ub4f1 \ub2e4\uc591\ud569\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {\n\n @Autowired\n private MethodSecurityService methodSecurityService;\n\n @Override\n protected MethodSecurityExpressionHandler createExpressionHandler() {\n DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();\n expressionHandler.setPermissionEvaluator(new MethodSecurityPermissionEvaluator(methodSecurityService));\n return expressionHandler;\n }\n}<\/code><\/pre>\n3. \uc138\uc158 \uad00\ub9ac(Session Management)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 \uc138\uc158 \uad00\ub9ac \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub3d9\uc2dc \ub85c\uadf8\uc778 \uc81c\uc5b4, \uc138\uc158 \ud0c0\uc784\uc544\uc6c3, \uc138\uc158 \uace0\uc815 \ubc29\uc9c0 \ub4f1\uc758 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.sessionManagement()\n .maximumSessions(1)\n .maxSessionsPreventsLogin(true)\n .sessionRegistry(sessionRegistry());\n }\n\n @Bean\n public SessionRegistry sessionRegistry() {\n return new SessionRegistryImpl();\n }\n}<\/code><\/pre>\n4. \ub85c\uadf8\uc778 \ud3fc \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5(Login Form Customizing)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c \ub85c\uadf8\uc778 \ud3fc\uc744 \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub85c\uadf8\uc778 \ud398\uc774\uc9c0\uc758 URL, \ub85c\uadf8\uc778 \ud3fc\uc758 \ud544\ub4dc\uba85\uc744 \ubcc0\uacbd\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.formLogin()\n .loginPage(\"\/login\")\n .loginProcessingUrl(\"\/authenticate\")\n .usernameParameter(\"email\")\n .passwordParameter(\"password\")\n .defaultSuccessUrl(\"\/home\")\n .failureUrl(\"\/login?error\");\n }\n}<\/code><\/pre>\n5. \ub85c\uadf8\uc544\uc6c3(Logout)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 \ub85c\uadf8\uc544\uc6c3 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub85c\uadf8\uc544\uc6c3 URL, \ub85c\uadf8\uc544\uc6c3 \ud6c4 \uc774\ub3d9\ud560 \ud398\uc774\uc9c0 \ub4f1\uc744 \uc124\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.logout()\n .logoutUrl(\"\/logout\")\n .logoutSuccessUrl(\"\/login?logout\")\n .invalidateHttpSession(true)\n .deleteCookies(\"JSESSIONID\");\n }\n}<\/code><\/pre>\n6. Remember Me<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 Remember Me \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74 \uc0ac\uc6a9\uc790\uac00 \ub85c\uadf8\uc544\uc6c3\ud55c \ud6c4\uc5d0\ub3c4 \ube0c\ub77c\uc6b0\uc800\ub97c \uc885\ub8cc\ud558\uc9c0 \uc54a\uace0, \ub2e4\uc74c\uc5d0 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \uc811\uc18d\ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ub85c\uadf8\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Autowired\n private DataSource dataSource;\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.rememberMe()\n .tokenRepository(persistentTokenRepository())\n .tokenValiditySeconds(1209600)\n .userDetailsService(userDetailsService());\n }\n\n @Bean\n public PersistentTokenRepository persistentTokenRepository() {\n JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();\n tokenRepository.setDataSource(dataSource);\n return tokenRepository;\n }\n}<\/code><\/pre>\n7. CSRF(Cross-Site Request Forgery)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 CSRF(Cross-Site Request Forgery) \uacf5\uaca9\uc744 \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ubc1c\uc0dd\ud55c \uc694\uccad\uc778\uc9c0 \ud655\uc778\ud558\uc5ec, CSRF \uacf5\uaca9\uc744 \ubc29\uc9c0\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.csrf()\n .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());\n }\n}<\/code><\/pre>\n8. CORS(Cross-Origin Resource Sharing)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 CORS(Cross-Origin Resource Sharing) \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \ub2e4\ub978 \ub3c4\uba54\uc778\uc5d0\uc11c \ud638\uc2a4\ud305\ub418\ub294 \ub9ac\uc18c\uc2a4\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub3c4\ub85d \ud5c8\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.cors();\n }\n\n @Bean\n public CorsConfigurationSource corsConfigurationSource() {\n CorsConfiguration configuration = new CorsConfiguration();\n configuration.setAllowedOrigins(Arrays.asList(\"*\"));\n configuration.setAllowedMethods(Arrays.asList(\"GET\", \"POST\", \"PUT\", \"DELETE\"));\n configuration.setAllowedHeaders(Arrays.asList(\"Authorization\", \"Content-Type\"));\n UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n source.registerCorsConfiguration(\"\/**\", configuration);\n return source;\n }\n}<\/code><\/pre>\n9. SSL(HTTPS)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 SSL(HTTPS) \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud074\ub77c\uc774\uc5b8\ud2b8 \uac04\uc758 \ud1b5\uc2e0\uc744 \uc554\ud638\ud654\ud558\uc5ec \ubcf4\uc548\uc744 \uac15\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Override\n protected void configure(HttpSecurity http) throws Exception {\n http.requiresChannel()\n .anyRequest()\n .requiresSecure();\n }\n}<\/code><\/pre>\n10. \ubcf4\uc548 \ub85c\uadf8(Security Log)<\/h3>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc5d0\uc11c\ub294 \ubcf4\uc548 \ub85c\uadf8 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ubc1c\uc0dd\ud55c \ubcf4\uc548 \uc774\ubca4\ud2b8\ub97c \ub85c\uadf8\ub85c \ub0a8\uaca8, \ubcf4\uc548 \uac15\ud654\uc5d0 \ub3c4\uc6c0\uc744 \uc904 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n
@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n @Autowired\n private AuthenticationEventPublisher authenticationEventPublisher;\n\n @Bean\n public LoggerListener loggerListener() {\n return new LoggerListener();\n }\n\n @Override\n protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n auth.authenticationEventPublisher(authenticationEventPublisher);\n }\n\n @Bean\n public AuthenticationEventPublisher authenticationEventPublisher() {\n return new DefaultAuthenticationEventPublisher();\n }\n}<\/code><\/pre>\n\uacb0\ub860<\/h1>\n
\uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\ub294 \uc778\uc99d\uacfc \uad8c\ud55c \ubd80\uc5ec\ub97c \uc704\ud55c \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc5ec, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubcf4\uc548\uc744 \uac15\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ubc88 \uae00\uc5d0\uc11c\ub294 \uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\uc758 \uc8fc\uc694 \uae30\ub2a5\ub4e4\uc744 \uc0b4\ud3b4\ubcf4\uc558\uc2b5\ub2c8\ub2e4. \uc2a4\ud504\ub9c1 \uc2dc\ud050\ub9ac\ud2f0\ub97c \ud65c\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ubcf4\uc548\uc744 \uac15\ud654\ud574\ubcf4\uc138\uc694!<\/p>\n","protected":false},"excerpt":{"rendered":"
Spring Security\ub97c \uc0ac\uc6a9\ud55c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ubcf4\uc548 \uac15\ud654 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc790.<\/p>\n","protected":false},"author":1,"featured_media":12882,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1957],"tags":[2058,5898,2105,2077,2079,2156,5932,2028],"class_list":["post-35106","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","tag-application","tag-backend","tag-java","tag-role","tag-security","tag-spring","tag-spring-boot","tag-your"],"acf":[],"_links":{"self":[{"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/posts\/35106","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/comments?post=35106"}],"version-history":[{"count":1,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/posts\/35106\/revisions"}],"predecessor-version":[{"id":35272,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/posts\/35106\/revisions\/35272"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/media\/12882"}],"wp:attachment":[{"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/media?parent=35106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/categories?post=35106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/m9js.shop\/blog\/wp-json\/wp\/v2\/tags?post=35106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}