이번에는 그 동안 어려운 부분을 봤으니, 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
-Ayotera Lab-
댓글