Подтвердить что ты не робот

Добавление дополнительных сведений к основному объекту, хранящемуся в spring контексте безопасности

Я использую Spring 3.0 и Spring Безопасность 3. Я могу аутентифицировать пользователя в отношении базы данных с помощью Spring Безопасность. Использование:

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

Я могу получить имя пользователя текущего зарегистрированного пользователя. Я хочу добавить дополнительные данные, такие как идентификатор пользователя, и модуль обращается к основному объекту, хранящемуся в Spring контексте безопасности, чтобы потом получить его. Как добавить дополнительную информацию к основному объекту, а затем как я могу получить его позже в классе jsp или java. Если возможно, укажите соответствующий фрагмент кода.

Изменить: я использую JDBC для доступа к моей базе данных.

Спасибо заранее.

4b9b3361

Ответ 1

Чтобы добавить дополнительную информацию к аутентифицированному пользователю. Сначала вы должны создать собственную реализацию объекта User, которая должна расширить объект пользователя безопасности w760. После этого вы можете добавить свойства, которые вы хотите добавить к аутентифицированному пользователю. Как только это будет сделано, вам нужно вернуть реализацию объекта пользователя в UserDeatailService (если вы не используете LDAP для аутентификации). Эта ссылка содержит сведения о добавлении дополнительной информации к аутентифицированному пользователю -

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

Ответ 2

(Предполагаю, что у вас есть базовая конфигурация безопасности Spring и знаете, как работают базовые компоненты)

Самый "правильный" способ обеспечит вашу собственную реализацию 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

"Единственное", что вам нужно сделать, это создать свою собственную UserDetailsService реализацию, которая возвращает вашу собственную реализацию UserDetails.

См. здесь для учебника, в котором реализована UserDetailsService на основе JPA.

Ответ 4

Вот что вам нужно:

  • Расширьте класс spring User (org.springframework.security.core.userdetails.User) и необходимые свойства.
  • Расширьте spring 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;

}

Пользовательские userdetails могут быть:

@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 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 или установить некоторые свойства.