我正在使用Spring 3.0和Spring Security 3.我能够使用Spring Security对数据库进行身份验证。使用:
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
我能够检索当前登录用户的用户名。我希望添加其他详细信息,例如用户ID和模块访问存储在Spring Security上下文中的主体对象,以便我以后可以检索它。如何向主体对象添加其他详细信息,然后如何在jsp或java类中检索它。如果可能,请提供相应的代码段。
编辑:我正在使用JDBC访问我的数据库。
提前致谢。
答案 0 :(得分:22)
为了向经过身份验证的用户添加更多详细信息。您需要首先创建自己的User对象实现,该实现应该扩展spring安全性User对象。之后,您可以添加要添加到经过身份验证的用户的属性。完成此操作后,您需要在UserDetailService中返回用户对象的实现(如果您未使用LDAP进行身份验证)。此链接提供了有关向经过身份验证的用户添加更多详细信息的详细信息 -
http://javahotpot.blogspot.in/2013/12/spring-security-adding-more-information.html
答案 1 :(得分:10)
以下是您的需求:
User
(org.springframework.security.core.userdetails.User
)类以及您需要的属性。UserDetailsService
(org.springframework.security.core.userdetails.UserDetailsService
)并填充上述物体。覆盖loadUserByUsername
并返回扩展用户类UserDetailsService
AuthenticationManagerBuilder
醇>
例如
public class CurrentUser extends User{
//This constructor is a must
public CurrentUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
//Setter and getters are required
private String firstName;
private String lastName;
}
自定义用户详细信息可以是:
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
//Try to find user and its roles, for example here we try to get it from database via a DAO object
//Do not confuse this foo.bar.User with CurrentUser or spring User, this is a temporary object which holds user info stored in database
foo.bar.User user = userDao.findByUserName(username);
//Build user Authority. some how a convert from your custom roles which are in database to spring GrantedAuthority
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
//The magic is happen in this private method !
return buildUserForAuthentication(user, authorities);
}
//Fill your extended User object (CurrentUser) here and return it
private User buildUserForAuthentication(foo.bar.User user,
List<GrantedAuthority> authorities) {
String username = user.getUsername();
String password = user.getPassword();
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new CurrentUser(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);
//If your database has more information of user for example firstname,... You can fill it here
//CurrentUser currentUser = new CurrentUser(....)
//currentUser.setFirstName( user.getfirstName() );
//.....
//return currentUser ;
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
return new ArrayList<GrantedAuthority>(setAuths);
}
}
配置spring安全上下文
@Configuration
@EnableWebSecurity
@PropertySource("classpath://configs.properties")
public class SecurityContextConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
一切都完成了!
您可以致电(CurrentUser)getAuthentication().getPrincipal()
新来CurrentUser
或设置一些属性。
答案 2 :(得分:9)
(我假设您有一个基本的Spring Security配置,并且知道基本组件如何协同工作)
最“正确”的方式是提供自己的AuthenticationProvider
实现,它返回自定义Authentication
实现。然后,您可以使用所需的一切填写此Authentication
实例。例如:
public class MyAuthentication extends UsernamePasswordAuthenticationToken implements Authentication {
public MyAuthentication(Object principal, Object credentials, int moduleCode) {
super(principal, credentials);
this.moduleCode = moduleCode;
}
public MyAuthentication(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities,int moduleCode) {
super(principal, credentials, authorities);
this.moduleCode = moduleCode;
}
private int moduleCode;
public getModuleCode() {
return moduleCode;
}
}
public class MyAuthenticationProvider extends DaoAuthenticationProvider {
private Collection<GrantedAuthority> obtainAuthorities(UserDetails user) {
// return granted authorities for user, according to your requirements
}
private int obtainModuleCode(UserDetails user) {
// return moduleCode for user, according to your requirements
}
@Override
public Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
// Suppose this user implementation has a moduleCode property
MyAuthentication result = new MyAuthentication(authentication.getPrincipal(),
authentication.getCredentials(),
obtainAuthorities(user),
obtainModuleCode(user));
result.setDetails(authentication.getDetails());
return result;
}
}
然后,在applicationContext.xml
:
<authentication-manager>
<authentication-provider ref="myAuthenticationProvider">
</authentication-manager>
<bean id="myAuthenticationProvider" class="MyAuthenticationProvider" scope="singleton">
...
</bean>
我想你可以通过提供AuthenticationDetails
和AuthenticationDetailsSource
的自定义实现来实现它,但我认为这将是一种不太干净的方法。
答案 3 :(得分:4)
您需要做的“唯一”事情是创建自己的UserDetailsService实现,它返回您自己的UserDetails对象实现。
有关实施基于JPA的UserDetailsService
。