我正在Spring中创建身份验证服务。
我正在使用UserDetailsService来获取表单变量,但我发现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;
}
//...
}
由于
答案 0 :(得分:17)
如果查看User对象,构造函数中的第二个参数就是密码。
UserDetailsService用于从像数据库这样的后端结构加载用户。当用户尝试使用用户名和密码登录时,将调用loadUserByUsername方法,然后服务负责加载用户定义并将其返回到安全框架。所需的详细信息包括username
,password
,accountNonExpired
,credentialsNonExpired
,accountNonLocked
和authorities
等数据。
一旦spring安全性收到用户对象,它将根据用户输入的密码和用户帐户状态等其他数据验证用户(accountNonExpired,credentialsNonExpired等)
答案 1 :(得分:9)
检索用户信息和提供身份验证信息的一些标准(开箱即用)机制是:
如果上述内容不适合您的目的,并且您需要自定义解决方案,则可以创建和配置新的身份验证提供程序,如下所示:
安全配置:
@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);
}
}