Search

์ธ์ฆ ๋ฐ ๊ถŒํ•œ ์ฒ˜๋ฆฌ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ

์ธ์ฆ ๋ฐ ๊ถŒํ•œ ์ฒ˜๋ฆฌ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ

โ€ข
๊ธฐ๋ณธ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹
โ€ข
์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๊ตฌํ˜„ํ•˜๊ธฐ
โ—ฆ
๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
โ—ฆ
๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ
โ—ฆ
๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
โ—ฆ
๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ ์ฒ˜๋ฆฌ
โ—ฆ
์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ

๊ธฐ๋ณธ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹

โ€ข
๋กœ๊ทธ์ธ ์„ฑ๊ณต
โ€ข
๋กœ๊ทธ์ธ ์‹คํŒจ
โ€ข
๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต
โ€ข
๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ
โ€ข
์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ
์ด๋ฒคํŠธ ์ข…๋ฅ˜
๊ธฐ๋ณธ ํ•ธ๋“ค๋Ÿฌ
๊ธฐ๋ณธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹
๋กœ๊ทธ์ธ ์„ฑ๊ณต
SavedRequestAwareAuthenticationSuccessHandler
์ด์ „ ์š”์ฒญ ๋˜๋Š” /๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
๋กœ๊ทธ์ธ ์‹คํŒจ
SimpleUrlAuthenticationFailureHandler
๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ, /login?error error ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€
๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต
SimpleUrlLogoutSuccessHandler
/login?logout logout ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€ ๋˜๋Š” ์„ค์ •๋œ URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ
(์‹คํŒจ ์ด๋ฒคํŠธ ์—†์Œ)
403 Forbidden ์‘๋‹ต
์ ‘๊ทผ ๊ฑฐ๋ถ€
AccessDeniedHandlerImpl
403 Forbidden ๋˜๋Š” ์„ค์ •๋œ ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™

๋กœ๊ทธ์ธ ์„ฑ๊ณต

๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ, ๋ฃจํŠธ ๊ฒฝ๋กœ โ€œ/โ€ (index.html) ๋ฉ”์ธํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

๋กœ๊ทธ์ธ ์‹คํŒจ

๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ, /login?error ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต

๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต ์‹œ, /login?logout ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ

๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ ์ด๋ฒคํŠธ๋Š” ์—†์Œ. 404 ์ด๊ฑฐ๋‚˜ 403(CSRF TOKEN) ๋“ฑ์˜ ๋กœ๊ทธ์•„์›ƒ ์š”์ฒญ ์ƒ์˜ ๋ฌธ์ œ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ ์‘๋‹ต

์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ

๊ถŒํ•œ์ด ์—†๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋ฅผ ์ ‘๊ทผ ํ•  ๋•Œ ex) ์‚ฌ์šฉ์ž (ROLE_USER) ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๊ฐ€ ๊ด€๋ฆฌ์ž (ROLE_ADMIN) ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋ฅผ ์š”์ฒญํ•  ๋•Œ, 403 Forbidden
Forbidden : ๊ธˆ์ง€๋œ

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๊ตฌํ˜„ํ•˜๊ธฐ

โ€ข
๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
โ€ข
๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ
โ€ข
๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
โ€ข
๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ ์ฒ˜๋ฆฌ
โ€ข
์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ
โ€ข
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ

LoginSuccessHandler.java

/** * ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ */ @Slf4j @Component public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { /** * ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์†Œ๋“œ * ๐Ÿช ์•„์ด๋”” ์ €์žฅ ์ฟ ํ‚ค ์ƒ์„ฑ * ๐Ÿ” ๋กœ๊ทธ์ธ ํ›„ ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ */ @Override public void onAuthenticationSuccess(HttpServletRequest request , HttpServletResponse response , Authentication authentication) throws ServletException, IOException { log.info("๋กœ๊ทธ์ธ ์„ฑ๊ณต..."); // ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด CustomUser customUser = (CustomUser) authentication.getPrincipal(); Users user = customUser.getUser(); log.info("์•„์ด๋”” : " + user.getUsername()); log.info("๋น„๋ฐ€๋ฒˆํ˜ธ : " + user.getPassword()); log.info("๊ถŒํ•œ : " + user.getAuthList()); super.onAuthenticationSuccess(request, response, authentication); } }
Java
๋ณต์‚ฌ

๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ

LoginFailureHandler.java

/** * ๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ์ž */ @Slf4j @Component public class LoginFailureHandler implements AuthenticationFailureHandler { /** * ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ, ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์†Œ๋“œ * ๐Ÿ”โŒ ๋กœ๊ทธ์ธ ์‹คํŒจ ํšŸ์ˆ˜ ์ฒดํฌ, ๋ณด์•ˆ ์ฒ˜๋ฆฌ * ( ๋กœ๊ทธ์ธ ์‹คํŒจ 5ํšŒ ๋ˆ„์  ์‹œ, ๋ณธ์ธ์ธ์ฆ ๋“ฑ ์š”์ฒญ ) */ @Override public void onAuthenticationFailure(HttpServletRequest request , HttpServletResponse response , AuthenticationException exception) throws IOException, ServletException { log.info("๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ ์‹คํŒจ..."); // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์—๋Ÿฌ ํฌํ•จ ์ „๋‹ฌ response.sendRedirect("/login?error"); } }
Java
๋ณต์‚ฌ

๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต ์ฒ˜๋ฆฌ

LogoutSuccesshandler.java

Java
๋ณต์‚ฌ

๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ ์ฒ˜๋ฆฌ

๋กœ๊ทธ์•„์›ƒ ์‹คํŒจ ์ด๋ฒคํŠธ๋Š” ์—†์Œ

์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ

AccessDeniedHandler.java

@Slf4j @Component public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request , HttpServletResponse response , AccessDeniedException accessDeniedException) throws IOException, ServletException { log.info("์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."); // ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ response.sendRedirect("/error/403"); } }
Java
๋ณต์‚ฌ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

SecurityConfig.java

@Slf4j @Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private DataSource dataSource; @Autowired private UserDetailServiceImpl userDetailServiceImpl; @Autowired private LoginSuccessHandler loginSuccessHandler; @Autowired private LoginFailureHandler loginFailureHandler; @Autowired private CustomAccessDeniedHandler customAccessDeniedHandler; // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ • ๋ฉ”์†Œ๋“œ @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // โœ… ์ธ๊ฐ€ ์„ค์ • http.authorizeHttpRequests(auth -> auth .requestMatchers("/admin", "/admin/**").hasRole("ADMIN") .requestMatchers("/user", "/user/**").hasAnyRole("USER","ADMIN") .requestMatchers("/**").permitAll() .anyRequest().permitAll() ); // ๐Ÿ” ํผ ๋กœ๊ทธ์ธ ์„ค์ • // โœ… ์ปค์Šคํ…€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ http.formLogin(login -> login.usernameParameter("id") // ์•„์ด๋”” ํŒŒ๋ผ๋ฏธํ„ฐ .passwordParameter("pw") // ๋น„๋ฐ€๋ฒˆํ˜ธ ํŒŒ๋ผ๋ฏธํ„ฐ .loginPage("/login") // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๊ฒฝ๋กœ .loginProcessingUrl("/login") // ๋กœ๊ทธ์ธ ์š”์ฒญ ๊ฒฝ๋กœ // .defaultSuccessUrl("/?success") // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ๊ฒฝ๋กœ .successHandler(loginSuccessHandler) // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ์ž ์„ค์ • // .failureUrl("/login?error") // ๋กœ๊ทธ์ธ ์‹คํŒจ ๊ฒฝ๋กœ .failureHandler(loginFailureHandler) // ๋กœ๊ทธ์ธ ์‹คํŒจ ์ฒ˜๋ฆฌ์ž ์„ค์ • ) ; // ๐Ÿ‘ฉโ€๐Ÿ’ผ ์‚ฌ์šฉ์ž ์ •์˜ ์ธ์ฆ http.userDetailsService(userDetailServiceImpl); // ๐Ÿ”„ ์ž๋™ ๋กœ๊ทธ์ธ ์„ค์ • http.rememberMe(me -> me.key("aloha") .rememberMeParameter("auto-login") .tokenRepository(tokenRepository()) .tokenValiditySeconds(60 * 60 * 24 * 7)); // 7์ผ ์œ ํšจ์‹œ๊ฐ„ (์ดˆ๋‹จ์œ„) // ์ธ์ฆ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ http.exceptionHandling( exception -> exception // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํŽ˜์ด์ง€ ์„ค์ • // .accessDeniedPage("/exception") // ์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌ์ž ์„ค์ • .accessDeniedHandler(customAccessDeniedHandler) ); return http.build(); } /** * ๐Ÿƒ ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” ๋นˆ ๋“ฑ๋ก * @return */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } /** * ๐Ÿƒ AuthenticationManager ์ธ์ฆ ๊ด€๋ฆฌ์ž ๋นˆ ๋“ฑ๋ก * @param authenticationConfiguration * @return * @throws Exception */ @Bean public AuthenticationManager authenticationManager( AuthenticationConfiguration authenticationConfiguration ) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } /** * ๐Ÿƒ JDBC ์ธ์ฆ ๋ฐฉ์‹ ๋นˆ ๋“ฑ๋ก * @return */ // @Bean // public UserDetailsService userDetailsService() { // JdbcUserDetailsManager userDetailsManager // = new JdbcUserDetailsManager(dataSource); // // ์‚ฌ์šฉ์ž ์ธ์ฆ ์ฟผ๋ฆฌ // String sql1 = " SELECT username, password, enabled " // + " FROM user " // + " WHERE username = ? " // ; // // ์‚ฌ์šฉ์ž ๊ถŒํ•œ ์ฟผ๋ฆฌ // String sql2 = " SELECT username, auth " // + " FROM user_auth " // + " WHERE username = ? " // ; // userDetailsManager.setUsersByUsernameQuery(sql1); // userDetailsManager.setAuthoritiesByUsernameQuery(sql2); // return userDetailsManager; // } /** * ๐Ÿƒ ์ž๋™ ๋กœ๊ทธ์ธ ์ €์žฅ์†Œ ๋นˆ ๋“ฑ๋ก * โœ… ๋ฐ์ดํ„ฐ ์†Œ์Šค * โญ persistent_logins ํ…Œ์ด๋ธ” ์ƒ์„ฑ create table persistent_logins ( username varchar(64) not null , series varchar(64) primary key , token varchar(64) not null , last_used timestamp not null ); * ๐Ÿ”„ ์ž๋™ ๋กœ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค * โœ… ๋กœ๊ทธ์ธ ์‹œ * โžก ๐Ÿ‘ฉโ€๐Ÿ’ผ(ID, ์‹œ๋ฆฌ์ฆˆ, ํ† ํฐ) ์ €์žฅ * โœ… ๋กœ๊ทธ์•„์›ƒ ์‹œ, * โžก ๐Ÿ‘ฉโ€๐Ÿ’ผ(ID, ์‹œ๋ฆฌ์ฆˆ, ํ† ํฐ) ์‚ญ์ œ * @return */ @Bean public PersistentTokenRepository tokenRepository() { // JdbcTokenRepositoryImpl : ํ† ํฐ ์ €์žฅ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฐ์ฒด JdbcTokenRepositoryImpl repositoryImpl = new JdbcTokenRepositoryImpl(); // โœ… ํ† ํฐ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ง€์ • // - ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์ž๋™ ๋กœ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ DB๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. repositoryImpl.setDataSource(dataSource); // ์„œ๋ฒ„ ์‹คํ–‰ ์‹œ, ์ž๋™ ๋กœ๊ทธ์ธ ํ…Œ์ด๋ธ” ์ž๋™ ์ƒ์„ฑ // repositoryImpl.setCreateTableOnStartup(true); // persistent_logins ํ…Œ์ด๋ธ” ์ƒ์„ฑ try { repositoryImpl.getJdbcTemplate().execute(JdbcTokenRepositoryImpl.CREATE_TABLE_SQL); } catch (BadSqlGrammarException e) { log.error("persistent_logins ํ…Œ์ด๋ธ”์ด ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."); } catch (Exception e) { log.error("์ž๋™ ๋กœ๊ทธ์ธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ค‘ , ์˜ˆ์™ธ ๋ฐœ์ƒ"); } return repositoryImpl; } }
Java
๋ณต์‚ฌ