Spring Security UserDetailsS​​ervice获取密码

时间:2013-02-18 14:40:50

标签: java spring-security

我正在Spring中创建身份验证服务。

我正在使用UserDetailsS​​ervice来获取表单变量,但我发现loadUserByUsername只有一个变量 - userName。

如何获取密码?

public class userAuthentication implements UserDetailsService{

    private @Autowired
    ASPWebServicesUtils aspWebServicesUtils;

    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {

        //how to get password ?

        User user = new User("test", "test", true, true, true, true, getAuthorities(true));

        return user;  

    }

    private List<GrantedAuthority> getAuthorities(boolean isAdmin){

        List<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>(2);
        authorityList.add(new SimpleGrantedAuthority("USER_ROLE"));
        if(isAdmin){
            authorityList.add(new SimpleGrantedAuthority("ADMIN_ROLE"));
        }
        return authorityList;

    }
//...
}

由于

7 个答案:

答案 0 :(得分:17)

如果查看User对象,构造函数中的第二个参数就是密码。

UserDetailsService用于从像数据库这样的后端结构加载用户。当用户尝试使用用户名和密码登录时,将调用loadUserByUsername方法,然后服务负责加载用户定义并将其返回到安全框架。所需的详细信息包括usernamepasswordaccountNonExpiredcredentialsNonExpiredaccountNonLockedauthorities等数据。

一旦spring安全性收到用户对象,它将根据用户输入的密码和用户帐户状态等其他数据验证用户(accountNonExpired,credentialsNonExpired等)

答案 1 :(得分:9)

检索用户信息和提供身份验证信息的一些标准(开箱即用)机制是:

  • inMemoryAuthentication
  • jdbcAuthentication
  • ldapAuthentication
  • 的UserDetailsS​​ervice

如果上述内容不适合您的目的,并且您需要自定义解决方案,则可以创建和配置新的身份验证提供程序,如下所示:

安全配置:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(new CustomAuthenticationProvider());
    }

    ....
}

身份验证提供商:

public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        String name = authentication.getName();
        // You can get the password here
        String password = authentication.getCredentials().toString();

        // Your custom authentication logic here
        if (name.equals("admin") && password.equals("pwd")) {
            Authentication auth = new UsernamePasswordAuthenticationToken(name,
                    password);

            return auth;
        }

        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}

答案 2 :(得分:3)

我相信UserDetailsService应该用于从某些后端存储,数据库,平面文件等中获取UserDetails对象。一旦你拥有了UserDetails,就可以使用{{1}} (或者您)必须将其与用户提供的用户名(或其他主体)和密码(凭据)进行比较,以便对该用户进行身份验证。

我不认为你按照预期的方式使用它。

答案 3 :(得分:1)

XML实施:

<authentication-manager  alias="loginAuthenticationManager">
    <authentication-provider ref="loginAuthenticationProvider" />
</authentication-manager>

<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="loginAuthenticationProvider" class="com.config.LoginAuthenticationProvider">
</beans:bean>

的AuthenticationProvider:

public class LoginAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        String name = authentication.getName();
        // You can get the password here
        String password = authentication.getCredentials().toString();

        // Your custom authentication logic here
        if (name.equals("admin") && password.equals("pwd")) {
            List<GrantedAuthority> grantedAuths = new ArrayList<>();
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
        }
        return null;
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

答案 4 :(得分:1)

添加到web.xml

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

UserDetailsService中获取密码

public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String password = request.getParameter("password"); // get from request parameter
        ......
    }
}

RequestContextHolder基于ThreadLocal

答案 5 :(得分:0)

loadUserByUsername(String name)是在接口上定义的方法(我认为是userServicedetails),您的服务实现了该方法。你必须编写实现。

就像你必须编写getPassword()或类似的实现一样...... spring没有提供。我想密码存储在你的用户对象中,但是你写了......你创建了一个getPassword()方法吗?

答案 6 :(得分:0)

我知道这个问题已经问了很久了。 我正处于类似场景的中间,我不仅需要在主体中添加名称以外的信息,还需要对用户进行身份验证。

我搜索了很多地方,但找不到答案。最后,我能够通过使用自定义AuthenticationProvider而不是用户详细信息服务来解决

创建自己的AppUser来扩展Spring用户

public class AppUser extends User {

    private static final long serialVersionUID = 1L;
    private String username;
    private List<String> adGroups;

    public AppUser(String username, List<String> adGroups) {
        super(username, "", true, true, true, true, new ArrayList<>());
        this.username = username;
        this.adGroups = adGroups;
    }
}

在身份验证提供程序中,扩展UsernamePasswordAuthenticationToken类以获取您的主体

public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private YourService yourService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        try {
            // Authenticate with LDAP or DB to get a userdetails bean with whatever 
            // things you need
            UserDetails userDetails = yourService.getUserDetails(username, password);
            final AppUser user = new AppUser(userDetails.getUsername(), userDetails.getAdGroups());
            return new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>()) {
                private static final long serialVersionUID = 1L;
                public Object getPrincipal() {
                    return user;
                }
            };
        } catch (Exception e) {
            log.error("Error while Authentication:" + e.getMessage(), e);
            return null;
        }
    }



    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}