簡體   English   中英

如何使用Spring Security以編程方式驗證`User`並使用我的`UserDetailsS​​ervie`實現?

[英]How to programmatically authenticate `User` with spring security and use my `UserDetailsServie` implementation?

我想將spring安全性UserDetailsService與spring data jpa CrudRepository接口一起使用。 委托人由實現UserDetails User實體表示:

@Entity
public class User implements UserDetails {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String username;
    private String password;

    //other methods of UserDetails 

我有spring-security.xml配置文件:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <authentication-manager>
        <!-- refers to spring data repository bean org.baeldung.SpringDataAuditDemo.dao.repos.UserDao -->
        <authentication-provider user-service-ref="userDao" />
    </authentication-manager>

</beans:beans>

它指的是豆userDao類型UserDetailsServiceCrudRepository

public interface UserDao extends CrudRepository<User, Long>, UserDetailsService {

    // @Override    
    @Query(value = "select u from User u where u.username=:username")
    public UserDetails loadUserByUsername(@Param("username") String username) throws UsernameNotFoundException;
}

現在,我想在jUnit測試中以編程方式驗證User對象。

我希望在對User進行身份驗證時運行UserDao.loadUserByUsername方法。 為此,我想使用org.springframework.security.provisioning.UserDetailsManager但它實現了UserDetailsService接口以及我的UserDao 因此,我有兩個相同類型的bean存在的例外!!!

然后,我嘗試使用UserDao代替UserDetailsManager但是我的UserDao不對User身份驗證,而僅從db加載它。 在這種情況下,不需要spring-security.xml

如何使用Spring Security默認DaoAuthenticationProvider以編程方式對User進行身份驗證並使用我的UserDetailsServie實現?

編輯

當我嘗試UserDao使用@QualifierUserDetailsManager自動連接UserDao時,出現此異常:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.provisioning.UserDetailsManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:494)
... 28 more

您可以使用AuthenticationManager對您的自定義UserDetailsS​​ervice進行編程身份驗證。 例如,以下將在JUnit測試中起作用:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SecurityConfigTests {

    @Autowired
    private AuthenticationManager manager;

    @Before
    public void setup() {
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        Authentication user = manager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
        context.setAuthentication(user);

        SecurityContextHolder.setContext(context);
    }
    ...
}

任何時候只要有多個相同類型的bean,就可以使用Qualifier注釋。 這意味着如果您收到一個異常,即存在兩個相同類型的bean,則可以指定所需的那個。 例如,如果要使用userDao的名稱作為UserDetailsS​​ervice Bean,則可以使用:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

...

@Qualifier("userDao")
@Autowired
UserDetailsService userDao;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM