Мне нужно аутентифицировать пользователя напрямую, используя какой-либо параметр.После создания действительного объекта аутентификации, как описано в справочной документации по безопасности, я вызываю 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 или отклоняет вызов без ошибки.