Java 向存储在 spring 安全上下文中的主体对象添加其他详细信息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20349594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:15:46  来源:igfitidea点击:

Adding additional details to principal object stored in spring security context

javaspringspring-security

提问by newUser

I am using Spring 3.0 and Spring Security 3. I am able to authenticate a user against a database using Spring Security. Using:

我正在使用 Spring 3.0 和 Spring Security 3。我能够使用 Spring Security 针对数据库对用户进行身份验证。使用:

SecurityContextHolder.getContext().getAuthentication().getPrincipal()

I am able to retrieve username of the current logged in user. I wish to add additional details like user id and the module accesses to the principal object stored in Spring Security context so that I can retrieve it later. How can I add additional details to the principal object and then how can I retrieve it later on a jsp or java class. Please provide an appropriate code snippet if possible.

我能够检索当前登录用户的用户名。我希望添加其他详细信息,例如用户 id 和模块访问存储在 Spring Security 上下文中的主体对象,以便我可以稍后检索它。如何向主体对象添加其他详细信息,然后如何在 jsp 或 java 类上检索它。如果可能,请提供适当的代码片段。

Edit: I am using JDBC to access my database.

编辑:我正在使用 JDBC 访问我的数据库。

Thanks in advance.

提前致谢。

采纳答案by Yogen

In order to add more details to the authenticated user. You need to first create your own implementation of the User object which should extend the spring security User object. After that you can add the properties you want to add to the authenticated user. Once this is done you need to return your implementation of the user object in UserDetailService (If you are not using LDAP for authentication). This link provides the details for adding more details to the authenticated user--

为了向经过身份验证的用户添加更多详细信息。您需要首先创建您自己的 User 对象的实现,它应该扩展 spring security User 对象。之后,您可以向经过身份验证的用户添加要添加的属性。完成此操作后,您需要在 UserDetailService 中返回用户对象的实现(如果您未使用 LDAP 进行身份验证)。此链接提供了向经过身份验证的用户添加更多详细信息的详细信息--

http://javahotpot.blogspot.in/2013/12/spring-security-adding-more-information.html

http://javahotpot.blogspot.in/2013/12/spring-security-adding-more-information.html

回答by gpeche

(I will assume you have a basic Spring Security configuration working and know how the basic components work together)

(我假设你有一个基本的 Spring Security 配置,并且知道基本组件是如何协同工作的)

The most "correct" way would be providing your own implementation of AuthenticationProvider, that return a custom Authenticationimplementation. Then you can fill in this Authenticationinstance with everything you need. For example:

最“正确”的方法是提供您自己的 实现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;
    }
}

And then, in applicationContext.xml:

然后,在applicationContext.xml

<authentication-manager>
    <authentication-provider ref="myAuthenticationProvider">
</authentication-manager>

<bean id="myAuthenticationProvider" class="MyAuthenticationProvider" scope="singleton">
    ...
</bean>

I guess you could get it working by providing custom implementations of AuthenticationDetailsand AuthenticationDetailsSource, but I think that would be a less clean approach.

我想你可以通过提供AuthenticationDetailsand 的自定义实现来让它工作AuthenticationDetailsSource,但我认为这会是一种不太干净的方法。

回答by M. Deinum

The "only" things you need to do is create your own UserDetailsServiceimplementation which returns your own implementation of a UserDetailsobject.

您需要做的“唯一”事情是创建您自己的UserDetailsS​​ervice实现,它返回您自己的UserDetails对象实现。

See herefor a tutorial which implements a JPA based UserDetailsService.

这里为它实现基于JPA的教程UserDetailsService

回答by Alireza Fattahi

Here is what you need:

这是您需要的:

  1. Extend spring User(org.springframework.security.core.userdetails.User) class and what ever properties you need.
  2. Extend spring UserDetailsService(org.springframework.security.core.userdetails.UserDetailsService) and fill the above object. Override loadUserByUsernameand return your extended user class
  3. Set your custom UserDetailsServicein AuthenticationManagerBuilder
  1. 扩展 spring User( org.springframework.security.core.userdetails.User) 类以及您需要的任何属性。
  2. 拉伸弹簧UserDetailsService( org.springframework.security.core.userdetails.UserDetailsService) 并填充上述对象。覆盖loadUserByUsername并返回您的扩展用户类
  3. 设置自定义UserDetailsServiceAuthenticationManagerBuilder

For example

例如

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;

}

The Custom userdetails could be:

自定义用户详细信息可以是:

@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);
}

}

Configure the spring security context

配置 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);
    }

It's all done !

这一切都完成了!

You can call (CurrentUser)getAuthentication().getPrincipal()to get you newly CurrentUseror set some properties.

你可以打电话(CurrentUser)getAuthentication().getPrincipal()给你新的CurrentUser或设置一些属性。