SpringSecurity身份验证用户:在SecurityContextHolder中的SecurityContext中设置OAuth2Authentication

时间:2019-02-06 13:01:45

标签: spring-security oauth-2.0 custom-authentication security-context

我需要使用某些参数直接验证用户身份。如安全参考文档中所述,构造了有效的身份验证对象后,我将调用SecurityContextHolder.getContext()。setAuthentication(authentication)。这是我的代码:

@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) {...}

}

当我发送用户ID为http://localhost:8080/api/esia/login/2的请求时,OAuth2Authentication已创建并保存在SecurityContextHolder中。我也从OAuth2AuthenticationDetails获取oauth2令牌值。收到令牌后,我将发送带有标头“ Authorization:Bearer token-value”的测试请求http://localhost:8080/api/esia/test,并获得http状态为401的响应。如果发送不带有认证标头的请求http://localhost:8080/api/esia/test,则用户被认证为匿名用户,但其中有我的主体(id = 2)的SecurityContext,之前已保存在customContextRepository中。我的猜测是SecurityContext会忽略我的呼叫setAuthentication或拒绝呼叫而不会出错。

0 个答案:

没有答案