Controller上的SecurityContextHolder.getContext()。getAuthentication()。getPrincipal()为null

时间:2017-08-18 13:20:48

标签: spring-mvc spring-security

我有一个Spring MVC应用程序,我正在暴露一个端点,还有一个小型库,我在其中编写了一些常用功能。

我有一个像这样的实用程序类:

class SecurityUtil {
    public static Principal getPrincipal(){
       return SecurityContextHolder.getContext().getAuthentication()
              .getPrincipal();
    } 
}

从控制器我做的事情是:

 class MyController {

      public ResponseEntity<Void> myEndpoint(){
           // do something
           Principal principal = SecurityUtil.getPrincipal();
           // use the principal information for some audit processes
      }
 }

在这种情况下,Principal为空,但如果替换我的代码如下:

 class MyController {

      public ResponseEntity<Void> myEndpoint(){
           // do something
           Principal principal = SecurityContextHolder.getContext()
                                                      .getAuthentication()
                                                      .getPrincipal();
           // use the principal information for some audit processes
      }
 }

在这种情况下,Principal不为空,它具有我需要的信息 你知道会发生什么吗?

1 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,然后我按照以下方式解决了这个问题。

创建UserService界面

public interface UserService {
    String getLoggedInUserName();
    User getLoggedInUser();
}

UserService提供实现,但是,您也可以在不创建界面的情况下,只需将UserService创建为类。

@Service
public class UserServiceImpl implements UserService { 

    private static Log log = LogFactory.getLog(UserServiceImpl.class);

    @Override
    public String getLoggedInUserName() {
        try {
            return getLoggedInUser().getUsername();
        } catch (Exception ex) {
            throw new UsernameNotFoundException("Please Log in", ex);
        }
    }

    @Override
    public User getLoggedInUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication.getPrincipal() instanceof User) {
            return (User) authentication.getPrincipal();
        } else {
            throw new UsernameNotFoundException("User is not authenticated; Found " + authentication.getPrincipal() + " of type " + authentication.getPrincipal().getClass() + "; Expected type User");
        }
    }

}

通过自动接线userService.getLoggedInUserName()

呼叫UserService
@Autowired UserService userService

更新: 如果只是在控制器中获取它们,那么您只需将Principal principal作为方法参数传递给控制器​​方法,而不是从安全上下文中获取它。它将自动连接到控制器,稍后您可以将其传递给您的服务方法。这种方式也被认为是一种很好的做法Spring MVC, getting principal from security context in service layer

@RequestMapping(value = "/myEndpoint", method = GET)
public ResponseEntity<Void> myEndpoint(Principal principal){
   // do something
   // use the principal information for some audit processes
}