Пользователь аутентификации SpringSecurity: настройка OAuth2Authentication в SecurityContext внутри SecurityContextHolder - PullRequest
0 голосов
/ 06 февраля 2019

Мне нужно аутентифицировать пользователя напрямую, используя какой-либо параметр.После создания действительного объекта аутентификации, как описано в справочной документации по безопасности, я вызываю SecurityContextHolder.getContext (). SetAuthentication (аутентификация).Это мой код:

@RequestMapping("/api/esia")
public class EsiaController {

@ResponseBody
@RequestMapping(value = "/auth/{id}", method = RequestMethod.GET)
public void auth(@PathVariable(name = "id") Long id,
                 HttpServletRequest request, HttpServletResponse response) throws IOException {//todo test
    AtomicReference<String> token = new AtomicReference<>();
    sysUsersRepository.findById(id).ifPresent(sysUsers -> {
        token.set(esiaAuthenticateProvider.authenticateToContext(sysUsers, request));
    });
    customContextRepository.saveContext("contextByString", SecurityContextHolder.getContext());
    response.sendRedirect("/test1/" + token.get());
}

@ResponseBody
@RequestMapping(value = "/test", method = RequestMethod.GET)
public User test(HttpServletRequest request, HttpServletResponse response) {//todo test
    SecurityContext context = customContextRepository.getContext("contextByString");
    if(context.getAuthentication() != SecurityContextHolder.getContext().getAuthentication()){
        log.info("Contexts don't equals");
    }
    return SecurityContextHolder.getContext().getAuthentication() != null ?
            (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal() :
            null;
}

};


@Service
public class CustomContextRepository {

private Map<String, SecurityContext> allContexts = new ConcurrentHashMap<>();
private Map<String, HttpSession> allSessions = new ConcurrentHashMap<>();

public void saveContext(String jsessionid, SecurityContext securityContext){
    allContexts.put(jsessionid, securityContext);
}

public SecurityContext getContext(String jsessionid){
    return allContexts.getOrDefault(jsessionid, null);
}

public void saveHttpSession(String jsessionid, HttpSession httpSession){
    allSessions.put(jsessionid, httpSession);
}

public HttpSession getHttpSession(String jsessionid){
    return allSessions.getOrDefault(jsessionid, null);
}

}

@Slf4j
@Service
@RequiredArgsConstructor
public class CustomEsiaAuthenticateProvider {
    ... 

  public String authenticateToContext(SysUsers sysUsers, HttpServletRequest httpRequest) {
    //возможно понадобится
    httpRequest.setAttribute("OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE", UUID.randomUUID().toString());
    httpRequest.setAttribute("OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE", "Bearer");
    AtomicReference<String> nextToken = new AtomicReference<>();
    createUserBySysUser(sysUsers).ifPresent(user -> {
        OAuth2AuthenticationDetails details = new OAuth2AuthenticationDetails(httpRequest);
        Map<String, String> cridetials = new HashMap<>();
        cridetials.put("username", user.getUsername());
        cridetials.put("password", user.getPassword());
        UsernamePasswordAuthenticationToken usernameToken =
                new UsernamePasswordAuthenticationToken(user, cridetials, user.getAuthorities());

        OAuth2Request customStoredRequest = createCustomStoredRequest(user.getUsername());
        OAuth2Authentication authentication = new OAuth2Authentication(customStoredRequest, usernameToken);
        authentication.setDetails(details);
        usernameToken.setDetails(details);
        authentication.setAuthenticated(true);
        authentication.getPrincipal();
        SecurityContext securityContext = SecurityContextHolder.getContext();
        if (securityContext != null) {
            securityContext.setAuthentication(authentication);
            HttpSession session = httpRequest.getSession(true);
            session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
            nextToken.set(details.getTokenValue());
        }
        SecurityContextHolder.getContextHolderStrategy().setContext(securityContext);
    });
    return nextToken.get();
}

 private OAuth2Request createCustomStoredRequest(String userLogin){...}

 private Optional<User> createUserBySysUser(SysUsers sysUsers) {...}

}

Когда я отправляю запрос с идентификатором пользователя http://localhost:8080/api/esia/login/2, OAuth2Authentication, созданная и сохраненная в SecurityContextHolder.Также я получаю значение токена oauth2 из OAuth2AuthenticationDetails.После получения токена я отправляю тестовый запрос http://localhost:8080/api/esia/test с заголовками «Авторизация: значение токена носителя» и получаю ответ со статусом http 401. Если отправляю запрос http://localhost:8080/api/esia/test без заголовков аутентификации, пользователь проходит аутентификациюкак анонимный пользователь, но есть SecurityContext с моим принципалом (id = 2), который был сохранен ранее в customContextRepository.Я предполагаю, что SecurityContext игнорирует мой вызов setAuthentication или отклоняет вызов без ошибки.

...