본문 바로가기
SpringBoot

[Spring Boot] 23. Spring Security (Etc)

by 청양호박이 2019. 12. 28.

이번에는 그 동안 어려운 부분을 봤으니, view를 구현하는 부분을 다른방법으로 최적화 해보도록 하겠습니다. 

 

 

1. AS-IS


현재 구현한 방식은 WebConfig에 addViewControllers를 통해서 resources > templates에 있는 html과 경로를 매핑하여 화면을 제공하였습니다. 이 방식에는 단점이라면 단점이 존재할 수 있는데... 페이지만 이동하는 get방식과 form을 통해서 이동이 필요한 post방식에 대한 논리적인 분리가 쉽지 않습니다. 그래서 아래과 같이 구현이 됬습니다.

 

[WebConfiguration.java]

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/home").setViewName("home");
	    registry.addViewController("/").setViewName("home");
	    registry.addViewController("/hello").setViewName("hello");
	    registry.addViewController("/userlogin").setViewName("userlogin");
	    registry.addViewController("/signup").setViewName("signup");
	    registry.addViewController("/user/main").setViewName("usermain");
	    registry.addViewController("/admin/main").setViewName("adminmain");
	}
	
}

그리고 각 페이지에 대한 접근 권한을 위해서 SecurityConfig에도 적용이 필요합니다. 단, Controller에 들어가는 경로역시 들어가야 하기때문에... 해당 예시에서 "/signup", "/usersignup"이 모두 추가가 되었습니다. 왜냐하면, 지정한 경로 외에는 .authenticated( )이기 때문에 무조건 로그인 페이지로 넘어가게 됩니다.

 

[SecurityConfiguration.java]

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
	
	@Autowired
	MyAuthenticationProvider myAuthenticationProvider;
	
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/static/css/**, /static/js/**, *.ico");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/", "/home", "/signup", "/usersignup").permitAll()
			.antMatchers("/user", "/user/**").hasRole("USER")
			.antMatchers("/admin", "/admin/**").hasRole("ADMIN")
			.anyRequest().authenticated();
		http.formLogin()
			.loginPage("/userlogin")
//			.usernameParameter("id")
//			.passwordParameter("pass")
			.defaultSuccessUrl("/#/todo")
			.permitAll();
		http.logout()
			.logoutUrl("/logout")
			.logoutSuccessUrl("/home")
			.invalidateHttpSession(true)
			.permitAll();
		http.exceptionHandling().accessDeniedPage("/user/deny");
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(myAuthenticationProvider);
	}
	
}

[ViewController.java]

@Controller
public class ViewController {

	final Logger L = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	MyUserDetailsService myUserDetailsService;
	
	@PostMapping("/usersignup")
	public String signupUser(UserDTO user) throws Exception {
		L.info("[POST] /usersignup :: Insert User in user_info table - {}", user);
		System.out.println(user);
		
		myUserDetailsService.signupUser(user);
		
		return "redirect:/home";
	}
	
}

동일한 페이지에 대해서 Security에도 등록하고 Controller에도 별도로 등록하는 것은 아무래도 비효율 적이지 않을 수 없습니다. 그래서 아래와 같이 구현하는게 더 효율적으로 생각됩니다.

 

 

2. To-Be


한개의 html파일은 무조건 하나의 경로로 매핑하고, 단 http method로 분리하여 controller에 구성합니다. 이렇게 되면, SecurityConfig에는 한개의 경로만 지정하고 신경을 쓸 필요가 없고... 모두 Controller에서 유동적으로 구현하면 됩니다.

 

변경된 모습은 아래와 같습니다.

 

[ViewController.java]

@Controller
public class ViewController {

	final Logger L = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	MyUserDetailsService myUserDetailsService;
	
	@GetMapping("/signup")
	public String goSignup() {
		return "/signup";
	}
	
	@PostMapping("/signup")
	public String signupUser(UserDTO user) throws Exception {
		L.info("[POST] /usersignup :: Insert User in user_info table - {}", user);
		System.out.println(user);
		
		myUserDetailsService.signupUser(user);
		
		return "redirect:/home";
	}
	
}

@GetMapping으로 동일한 경로를 구성하여, 해당 html page를 view로 매핑하고... 기존처럼 Form을 통해서 post로 동일경로로 들어온다면 회원가입을 처리하고 /home으로 redirect되게 됩니다. 관련된 항목들은 주석처리를 하거나 삭제하면 되겠습니다.

 

대상 : SecrurityConfiguration.java, WebConfiguration.java

 

[SecurityConfiguration.java]

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
//			.antMatchers("/", "/home", "/signup", "/usersignup").permitAll()
			.antMatchers("/", "/home", "/signup").permitAll()
			.antMatchers("/user", "/user/**").hasRole("USER")
			.antMatchers("/admin", "/admin/**").hasRole("ADMIN")
			.anyRequest().authenticated();
		http.formLogin()
			.loginPage("/userlogin")
//			.usernameParameter("id")
//			.passwordParameter("pass")
			.defaultSuccessUrl("/#/todo")
			.permitAll();
		http.logout()
			.logoutUrl("/logout")
			.logoutSuccessUrl("/home")
			.invalidateHttpSession(true)
			.permitAll();
		http.exceptionHandling().accessDeniedPage("/user/deny");
	}
	

[WebConfiguration.java]

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/home").setViewName("home");
	    registry.addViewController("/").setViewName("home");
	    registry.addViewController("/hello").setViewName("hello");
	    registry.addViewController("/userlogin").setViewName("userlogin");
//	    registry.addViewController("/signup").setViewName("signup");
	    registry.addViewController("/user/main").setViewName("usermain");
	    registry.addViewController("/admin/main").setViewName("adminmain");
	}
	
}

정상적으로 동작됨을 확인할 수 있습니다.

 

 

0. 마치며


지금까지 구현한 모든 소스코드는 아래의 GitHub에서 확인가능합니다.

 

https://github.com/ssayoung/ayotest

 

ssayoung/ayotest

Test repository. Contribute to ssayoung/ayotest development by creating an account on GitHub.

github.com

 

-Ayotera Lab-

댓글