Spring安全上下文手动身份验证给出奇怪的结果

时间:2019-06-20 04:19:19

标签: spring spring-mvc spring-security

我已通过使用HandlerInterceptor和SoapHandler拦截传入的休息/肥皂请求,在休息/肥皂服务调用中手动添加了Spring身份验证。我将登录的用户名从客户端添加到Web服务,方法是将其添加到soap / rest标头中。我拦截了传入请求并设置了手动身份验证。当我发现认证已经存在时,我将跳过设置。我假设对于每个新的休息/肥皂请求,Web服务(服务器端)都不会进行身份验证。它给我的用户名不是当前用户的新请求。

public UserDetails getUser() {

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    UserDetails user= null;
    if (auth != null && !(auth instanceof AnonymousAuthenticationToken)) {
        // userDetails = auth.getPrincipal()

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        String username = null;
        if (principal instanceof UserDetails) {
            username = ((UserDetails) principal).getUsername();
            user= (UserDetails ) principal;

        } else {
            username = principal.toString();
        }       
    }

    return user;
}

public void setUser(String username) {

    // creating spring security context manually

    try {
        // Must be called from request filtered by Spring Security,
        // otherwise SecurityContextHolder is not updated
        List<SimpleGrantedAuthority> grantedAuthorities = new ArrayList<SimpleGrantedAuthority>();
        Authentication authentication;
        authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) {
            Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            UserDetails user;

            String uname;
            if (principal instanceof UserDetails) {
                user= (User) principal;
                uname = user.getUsername();                 
            } else {
                uname = principal.toString();
            }
            LOGGER.info("Found username in Spring context: " + uname);
        } else {
            LOGGER.info("Spring context not found: ");
            LOGGER.info("Setting manual authentication.. Username: " + username);
            // grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
            UserDetails contextUser = new User(username, username, true, true, true, true,
                    grantedAuthorities, null);
            authentication = new UsernamePasswordAuthenticationToken(contextUser, username, grantedAuthorities);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (Exception e) {
        SecurityContextHolder.getContext().setAuthentication(null);
        LOGGER.error("Failure in creating spring security context authentication", e);
    }
}

1 个答案:

答案 0 :(得分:1)

这是因为SecurityContext存储在ThreadLocal中,并且在Web服务线程完成对请求的处理之后,您从未从ThreadLocal中清除它,这意味着是否有相同的线程用于处理下一个请求,它仍然保留上一个请求的SecurityContext。准确地说,在您的情况下,它始终保留第一个使用该线程的用户。

快速的解决方法是您必须在完成每个请求后清除SecurityContext

SecurityContextHolder.clearContext();