MelRanG
729
2021-08-30 15:19:11
2
150

h2 db, oauth2, mustache 세션 유지 관련 질문드립니다.


안녕하십니까 h2와 Oauth2를 사용해 로그인을 구현중입니다.

세션에 값을 넣었고 mustache에 #userName으로 로그인, 로그아웃을 구현하는중입니다.

메인 페이지에서 로그인을 하면 로그아웃 표시가 뜨는데 페이지 이동시 다시 로그인표시가 뜹니다.

그런데 로그인이 풀린 건 아닌지 글쓰기는 가능한데 왜 그런지 모르겠습니다. SPRING_SESSION 테이블에 세션이 들어간 것도 확인했습니다.


controller에서 페이지마다 user를 건네주면 해결이 되는데 이렇게 해결하는건 아닌 것 같습니다 ㅠㅠ


OAuth2UserService
@RequiredArgsConstructor
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    private final UserRepository userRepository;
    private final HttpSession httpSession;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails()
                .getUserInfoEndpoint().getUserNameAttributeName();

        OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());

        User user = saveOrUpdate(attributes);
        httpSession.setAttribute("user", new SessionUser(user));

        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority(user.getRoleKey())),
                attributes.getAttributes(),
                attributes.getNameAttributeKey());
    }


    private User saveOrUpdate(OAuthAttributes attributes) {
        User user = userRepository.findByEmail(attributes.getEmail())
                .map(entity -> entity.update(attributes.getName(), attributes.getPicture()))
                .orElse(attributes.toEntity());

        return userRepository.save(user);
    }
}


controller

@RequiredArgsConstructor
@Controller
public class indexController {

    private final PreferencePerfumeService preService;
    private final HttpSession httpSession;

    @GetMapping("/")
    public String index(Model model, @LoginUser SessionUser user){
        model.addAttribute("prePerfume", preService.findAllDesc());
        if (user != null){
            model.addAttribute("userName", user.getName());
        }
        return "index";
    }

    @GetMapping("/perfume/save")
    public String perfumeSave(){
        return "perfume-save";
    }
}

perfume-save


{{>layout/header}}

{{>layout/footer}}

header


<nav class = "navbar navbar-expand-lg navbar-light bg-light">
    <div class="container px-4 px-lg-5">
        <a class="navbar-brand" href="/">Perfume Service</a>
        <div class="navbar-collapse collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0 ms-lg-4">
                {{#userName}}
                <li class="nav-item">
                    <span class="nav-link active" id="user" aria-current="page">{{userName}}</span>

                </li>
                <li class="nav-item">
                    <a href="/logout" class="nav-link active" role="button">Logout</a>
                </li>
                {{/userName}}
                {{^userName}}
                <li class="nav-item">
                    <a href="/oauth2/authorization/google" class="nav-link active" aria-current="page" >구글로그인</a>
                </li>
                <li class="nav-item">
                    <a href="/oauth2/authorization/naver" class="nav-link active" aria-current="page" >네이버로그인</a>
                </li>
                {{/userName}}
            </ul>
        </div>
        <div class="col-lg-4">
            <form action="" method="GET">
                <input type="text" class = "form-control rounded-pill" placeholder="향수명 검색" aria-describedby="button-addon2">
            </form>
        </div>
</nav>


0
  • 답변 2

  • 훈마로
    973
    2021-08-30 15:48:01

    @LoginUser 커스텀 어노테이션을 설정한 부분과 인터셉터를 보여주셔야 될 것 같아요.

    HttpSession에 user를 저장하셨으니, @LoginUser 어노테이션이 있을 경우 HttpSession에서 꺼내와서 세팅하는 내용이 있나요?

  • MelRanG
    729
    2021-08-30 16:02:53

    훈마로

    LoginUser.java

    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser {
    }


    LoginUserArgumentResolver.java

    @RequiredArgsConstructor
    @Component
    public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

    private final HttpSession httpSession;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
    boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;
    boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());
    return isLoginUserAnnotation && isUserClass;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    return httpSession.getAttribute("user");
    }
    }

    webConfig.java

    @RequiredArgsConstructor
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    private final LoginUserArgumentResolver loginUserArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(loginUserArgumentResolver);
    }
    }


    따로 인터셉터가 있는건진 잘 모르겠습니다... 책을 보면서 제 프로젝트로 변형해서 진행하다보니...ㅠ 

    로그인 설정은 이게 끝입니다!


    @LoginUser 어노테이션이 있을 경우 HttpSession에서 꺼내와서 세팅하는 내용이 있나요?

    이 부분은 혹시 이것을 말씀하시는건가요?

        @GetMapping("/")
        public String index(Model model, @LoginUser SessionUser user){
            model.addAttribute("prePerfume", preService.findAllDesc());
            if (user != null){
                model.addAttribute("userName", user.getName());
            }
            return "index";
        }





  • 로그인을 하시면 답변을 등록할 수 있습니다.