SpringBoot [스프링부트] Spring Security Baisc (3)
전 글에서 인증과 권한에 대해 다뤘고, 같은 권한을 가진 User는 다른 User의 리소스에 접근할 수 있었습니다. Interceptor를 통해서 인가 문제를 해결해보겠습니다.
1. Interceptor란?
인터셉터(Interceptor)는 스프링의 Spring Context(ApplicationContext) 기능입니다.
임의의 URI를 호출 시 DispatcherServlet에서 해당 Controller가 처리되기 전과 후에 발생하는 것을 처리할 수 있습니다.
즉 DispatcherServlet -> Interceptor -> Controller -> Interceptor -> ~~ 로 표현할 수 있습니다.
2. UserController 수정
@PostMapping("/character") public String create(@RequestParam(name = "name") String name, HttpServletRequest request){ HttpSession session = request.getSession(false); String email = (String) session.getAttribute("email"); Character character = userService.createCharacter(name, email); return "ok"; }
- 더 이상 로그인을 한 User에게서는 RequestParam으로 User 정보를 받지 않고, 인증을 성공한 User에 한해서 CustomLoginSuccessHandler에서 session을 만들고 정보를 넣습니다. 이제 Controller에서는 HttpServlerRequest에서 session을 꺼내 어떠한 User인지 알 수 있습니다.
3. CustomLoginSuccessHandler 수정
public class CustomLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { SecurityContextHolder.getContext().setAuthentication(authentication); String email = authentication.getName(); HttpSession session = request.getSession(); session.setAttribute("email",email); response.sendRedirect("/success"); } }
- Authentication.getName()을 통해서 User의 email을 꺼내고 session을 성성하고 정보를 넣습니다.
session과 코드의 중복을 줄이는 ArgumentResolver를 알아보고 싶으시면 아래 링크들에서 확인 부탁드립니다:)
SpringBoot [스프링부트] 시작하기(6) MemberController 만들기
UserController를 만들었던 거 처럼 MemberController를 만들겠습니다. 1. MemberController Controller위에 @RequestMapping("member")을 주면 모든 메소드에 적용됩니다. /member/~~이런식으로 식별됩니다. @Pos..
dingdingmin-back-end-developer.tistory.com
SpringBoot [스프링부트] 시작하기(7) ArgumentResolver 만들기
전 시간에 Controller에서 Session을 가져오는 데 있어서 중복 코드가 있었습니다. 해당 코드를 ArgumentResolver로 해결해보겠습니다. ArgumentResolver란? 컨트롤러의 메소드의 인자로 사용자가 임의의 값을
dingdingmin-back-end-developer.tistory.com
4. CharacterRepository 수정 (fetch join을 추가해줍니다.)
public interface CharacterRepository extends JpaRepository<Character, Long> { @Query("select c from Character c join fetch c.user where c.id= :id") Optional<Character> findFetchById(@Param("id") Long id); }
5. CharacterInterceptor추가 (주석을 통한 설명)
@RequiredArgsConstructor @Component public class CharacterInterceptor implements HandlerInterceptor { private final CharacterRepository characterRepository; //Filter 에서 이미 권한에 관한 것을 처리했으므로 인가에 관해서만 처리합니다. @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // URI 즉 localhost:8080의 그 뒷부분이 해당합니다. String requestURI = request.getRequestURI(); //session 을 통해서 어느 User 가 요청했는지 알 수 있습니다. String email = (String) request.getSession().getAttribute("email"); //Post 에 관해서는 자신의 캐릭터를 만드는 것이므로 모두 접근 가능하지만 Patch 에 관해서는 자신이 소유한 것만 가능하므로 체크해줍니다. if(requestURI.contains("/character") && request.getMethod().equals("PATCH")){ //Patch 를 하는 캐릭터의 id 입니다. long id = Long.parseLong(request.getParameter("id")); Character character = characterRepository.findFetchById(id).get(); if(!character.getUser().getEmail().equals(email)){ // 인가 되지 않으므로 /notAccess 로 redirect합니다. response.sendRedirect("/notAccess"); // false 일 경우 원래 접근하고자 하는 uri에 요청을 보내지 않습니다. // return false를 해주지 않으면 밑에 로직들이 실행되므로 반드시 해줘야합니다. return false; } } else{ return true; } // return true 이므로 자원에 접근할 수 있습니다. return true; } }
6. WebConfig 추가
@EnableWebMvc @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final CharacterRepository characterRepository; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CharacterInterceptor(characterRepository)) .addPathPatterns("/character") // "/character"에 대해서만 Interceptor를 적용합니다. .excludePathPatterns("/signup","/login","/notAccess","/user","/guest","/"); // 적어준 uri에 대해선 Interceptor를 적용하지 않습니다. } }
7. Postman test
- asdf User와 qwer User가 가입을 합니다.


- asdf User가 로그인을 한 후 Character를 만듭니다.


- asdf User는 Character의 이름을 업데이트가 가능합니다.

- qwer User가 로그인을 한 후 asdf User가 만든 Character에 대해서 인가가 되어 수정이 가능한지 보겠습니다.

- 수정이 불가능한 것을 볼 수 있습니다.

지금까지 Security의 Filter를 직접 만들어 권한과 인증처리를 완료했고, Interceptor를 통해서 인가에 대한 처리를 완료했습니다. Security에 전반적인 부분을 살펴보았습니다. 감사합니다.
모든 코드는 아래 링크에서 확인 가능합니다.
https://github.com/rlaehdals/secuitybasic
GitHub - rlaehdals/secuitybasic
Contribute to rlaehdals/secuitybasic development by creating an account on GitHub.
github.com
'SpringBoot > spring security' 카테고리의 다른 글
Springboot[스프링부트] Spring Security Basic(5) 동작 과정 (0) | 2022.05.13 |
---|---|
Springboot [스프링부트] Spring Sercurity Basic(4) (0) | 2022.02.12 |
SpringBoot [스프링부트] Spring Security Basic(2) (0) | 2022.01.27 |
SpringBoot [스프링 부트] Spring Security Basic (1) 프로젝트 생성 (0) | 2022.01.25 |
SpringBoot [스프링부트] Spring Security Basic (0) (0) | 2022.01.25 |
댓글
이 글 공유하기
다른 글
-
Springboot[스프링부트] Spring Security Basic(5) 동작 과정
Springboot[스프링부트] Spring Security Basic(5) 동작 과정
2022.05.13 -
Springboot [스프링부트] Spring Sercurity Basic(4)
Springboot [스프링부트] Spring Sercurity Basic(4)
2022.02.12 -
SpringBoot [스프링부트] Spring Security Basic(2)
SpringBoot [스프링부트] Spring Security Basic(2)
2022.01.27 -
SpringBoot [스프링 부트] Spring Security Basic (1) 프로젝트 생성
SpringBoot [스프링 부트] Spring Security Basic (1) 프로젝트 생성
2022.01.25
댓글을 사용할 수 없습니다.