2009-07-23 4 views
1

Я настроил Весенний боб следующим образом вернуть SecurityContext:Spring Security: возвращает Authentication обнулить

<bean id="securityContext" class="org.springframework.security.context.SecurityContextHolder" 
    factory-method="getContext"> 
</bean> 

Когда я использую этот компонент объект Authentication возвращает нуль.

Authentication authentication = securityContext.getAuthentication(); 
GrantedAuthority[] authorities = authentication.getAuthorities(); 

Вторая строка выше вызывает NPE. Что кажется странным для меня, так как следующий код возвращает власть, как ожидалось:

GrantedAuthority[] authorities = 
SecurityContextHolder.getContext().getAuthentication().getAuthorities(); 

В основном я пытаюсь устранить статический вызов SecurityContextHolder.getContext(), чтобы сделать мой код более проверяемым.

Любые мысли о том, как исправить это? Почему SecurityContext, возвращенный Spring, не может вернуть полномочия, в то время как статический вызов из моего собственного кода может?

FYI Я выполняю код из действия Struts 2.

ответ

2

SecurityContextHolder.getContext() возвращает контекст, связанный с текущим потоком. В экземпляре bean-компонента контекст, хранящийся в вашем компоненте, отличается от контекста, который вам нужен, когда приложение работает. Я не думаю, что можно сохранить контекст в компоненте и использовать его все время.

+1

Я согласен с этим, не сражайтесь с каркасом. – JamesC

+2

Это хорошее описание проблемы, но не решение. – msangel

0

Вы можете сделать свой код поддающимся проверке, используя статический подход. Вам просто нужно создать свою собственную реализацию org.springframework.security.Authentication

Так что в вашем JUnit Test ...

//Assuming you've loaded the user, create your stub 
Authentication authentication = new TestAuthentication(userDetails); 
//Update the context 
SecurityContextHolder.getContext().setAuthentication(authentication); 

В приведенном выше примере «UserDetails» класс, который реализует «UserDetails 'и обычно обертывает объект User вашего домена.

Моего TestAuthentication класс - надеется, что это помогает

public class TestAuthentication implements Authentication { 

    private UserDetails userDetails; 
    private boolean authentication = true; 

    public TestAuthentication(UserDetails userDetails){ 
     NullArgumentException.assertNotNull(userDetails, "userDetails"); 
     this.userDetails = userDetails; 
    } 

    public TestAuthentication(UserDetails userDetails, boolean authentication){ 
     NullArgumentException.assertNotNull(userDetails, "userDetails"); 
     this.userDetails = userDetails; 
     this.authentication = authentication; 
    } 


    public GrantedAuthority[] getAuthorities() { 
     return userDetails.getAuthorities(); 
    } 


    public Object getCredentials() { 
     return null; 
    } 


    public Object getDetails() { 
     return null; 
    } 


    public Object getPrincipal() { 
     return this.userDetails; 
    } 


    public boolean isAuthenticated() { 
     return authentication; 
    } 


    public void setAuthenticated(boolean arg0) 
      throws IllegalArgumentException { 
     this.authentication = arg0; 
    } 


    public String getName() { 
     return null; 
    } 
} 
+0

Спасибо за предложение. Похоже, что было бы намного проще, если бы контекст безопасности мог быть введен, так как тогда его можно было бы издеваться. Вместо этого с этим подходом я должен создать кучу тестовых dummys и заглушек, в том числе для аутентификации и GrantedAuthority. Но в конечном итоге это тот подход, который мне пришлось принять. :-) – 2009-07-27 21:43:46

+0

Вы можете легко использовать насмешливый объект UserDetails и передать его в setAuthentication. Аутентификация аутентификации = EasyMock.createNiceMock (Authentication.class); EasyMock.expect (authentication.getPrincipal()) .Return (userDetails); SecurityContextHolder.getContext(). SetAuthentication (аутентификация); –

0

Это происходит, так как бин вы создали не определяют scope- так это в основном синглтон. Чтобы сделать его работу по вашему желанию, вам необходимо сделать запрос/сеанс.

Смежные вопросы