@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired AuthProvider authProvider; @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.csrf().disable(); // 개발 시 에만 http.authorizeRequests() .antMatchers("/user/**").access("ROLE_USER") // 사용자 페이지 .antMatchers("/admin/**").access("ROLE_ADMIN") // 관리자 페이지 .antMatchers("/login").permitAll() .antMatchers("/**").authenticated(); http.formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .usernameParameter("id") .passwordParameter("password"); http.logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/") .invalidateHttpSession(true); http.authenticationProvider(authProvider); }
@Component @Slf4j public class AuthProvider implements AuthenticationProvider{ @Autowired MemberService service; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String userId = authentication.getName(); String userPw = authentication.getCredentials().toString(); return authenticate(userId, userPw); } private Authentication authenticate(String id, String pw) throws AuthenticationException { Member m = new Member(id, pw); m = service.getMemberByUserName(id); if ( m == null || !m.getPw().equals(pw)) { log.error("{} is not exist or password is not equals", id); return null; } List코드에 대한 설명은 딱히 필요 없을 정도로 간단하다. MyAuthentication.java 는 아래와 같다.authList = new ArrayList<>(); /** * Role 처리 필요, 일단 임의로 USER Role을 부여한다. **/ authList.add(new SimpleGrantedAuthority("ROLE_USER")); return new MyAuthentication(id, pw, authList, m); } @Override public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } }
@Setter @Getter public class MyAuthentication extends UsernamePasswordAuthenticationToken{ private static final long serialVersionUID = 1L; Member member; public MyAuthentication(String id, String pw, ListauthList, Member member) { super(id, pw, authList); this.member = member; } }
이제 Spring Security 를 통해 제공되는 login page 에서 ID/PW 를 입력하면
AuthProvider 를 통해 실제 DB 에 있는 사용자 값(ID, PW)을 확인하여 인증하게 된다.
물론 이건 테스트 코드이기 때문에 PW 에 대한 암호화는 생략해 둔 상태이다.
Spring Security 에서 제공하는 login page 는 테스트를 위해 사용하고 실제로는 그래도 조금 예쁜(?) 로그인 페이지가 필요하다.
SecurityConfig.java 에서 http.formLogin() .loginPage("/login") 로 설정해 두었으니 그에 알맞은 controller 와 login page (.html)을 만들어 보자.
@RequestMapping(value="/login", method=RequestMethod.GET) public String login(Model model, String error, String logout) { if ( error != null ) { model.addAttribute("errorMsg", "Your username and password are invalid."); } if ( logout != null ) { model.addAttribute("msg", "You have been logged out successfully"); } return "login.html"; }
실제로 로그인을 성공하면 (DB에 있는 값으로 ID/PW 입력) vue 로 만들어둔 home 화면이 나온다.
home 에서 user page 와 admin page 는 vue router 를 이용하여 SPA 로 만든 상태다.
여기서 문제가 하나 생긴다.
Spring Security 를 통해 인증을 하고 Role 을 통해 메뉴/페이지별로 권한을 체크하도록 해 두었는데
SPA 의 경우 Server 로 요청하지 않고 Front End 에서 화면 변화가 일어나기 때문에
Spring Security에서 설정해 둔 ROLE 은 무의미하게 되는 것이다.
다시 말하면, 현재 임시로 로그인에 성공할 경우 "ROLE_USER" 권한을 부여해 두었고 Spring Security 에서는 아래 소스코드를 통해
http.authorizeRequests() .antMatchers("/user/**").access("ROLE_USER") // 사용자 페이지 .antMatchers("/admin/**").access("ROLE_ADMIN") // 관리자 페이지 .antMatchers("/login").permitAll() .antMatchers("/**").authenticated();
'IT > Web' 카테고리의 다른 글
Vue.js - Module build failed: Error: "extract-text-webpack-plugin" loader is used without the corresponding plugin, refer to https://github.com/webpack/extract-text-webpack-plugin for the usage example at Object.pitch (0) | 2018.09.21 |
---|---|
Vue.js + ajax + Spring Boot (0) | 2018.09.20 |
Vue.js - Route 시 # 없애기 (0) | 2018.09.05 |
Vue.js - Vuex (상태관리) (0) | 2018.09.03 |
톰캣 일반계정으로 실행 (0) | 2014.11.25 |