Saltar al contenido

¿Cómo agregar un cliente usando JDBC para ClientDetailsServiceConfigurer en Spring?

Solución:

Siga estos pasos:

  1. coloque este schema.sql dentro de su carpeta de recursos para que SpringBoot lo detecte una vez que inicie su servidor. Si no usa Spring Boot, no se preocupe, simplemente importe este script desde cualquier cliente de aplicaciones Mysql (phpmyadmin, HeidiSQL, Navicat ..)

    drop table if exists oauth_client_details;
    create table oauth_client_details (
    client_id VARCHAR(255) PRIMARY KEY,
    resource_ids VARCHAR(255),
    client_secret VARCHAR(255),
    scope VARCHAR(255),
    authorized_grant_types VARCHAR(255),
    web_server_redirect_uri VARCHAR(255),
    authorities VARCHAR(255),
    access_token_validity INTEGER,
    refresh_token_validity INTEGER,
    additional_information VARCHAR(4096),
    autoapprove VARCHAR(255)
    );
    drop table if exists oauth_client_token;
    create table oauth_client_token (
    token_id VARCHAR(255),
    token LONG VARBINARY,
    authentication_id VARCHAR(255) PRIMARY KEY,
    user_name VARCHAR(255),
    client_id VARCHAR(255)
    );
    drop table if exists oauth_access_token;
    create table oauth_access_token (
    token_id VARCHAR(255),
    token LONG VARBINARY,
    authentication_id VARCHAR(255) PRIMARY KEY,
    user_name VARCHAR(255),
    client_id VARCHAR(255),
    authentication LONG VARBINARY,
    refresh_token VARCHAR(255)
    );
    drop table if exists oauth_refresh_token;
    create table oauth_refresh_token (
    token_id VARCHAR(255),
    token LONG VARBINARY,
    authentication LONG VARBINARY
    );
    drop table if exists oauth_code;
    create table oauth_code (
    code VARCHAR(255), authentication LONG VARBINARY
    );
    drop table if exists oauth_approvals;
    create table oauth_approvals (
    userId VARCHAR(255),
    clientId VARCHAR(255),
    scope VARCHAR(255),
    status VARCHAR(10),
    expiresAt TIMESTAMP,
    lastModifiedAt TIMESTAMP
    );
    drop table if exists ClientDetails;
    create table ClientDetails (
    appId VARCHAR(255) PRIMARY KEY,
    resourceIds VARCHAR(255),
    appSecret VARCHAR(255),
    scope VARCHAR(255),
    grantTypes VARCHAR(255),
    redirectUrl VARCHAR(255),
    authorities VARCHAR(255),
    access_token_validity INTEGER,
    refresh_token_validity INTEGER,
    additionalInformation VARCHAR(4096),
    autoApproveScopes VARCHAR(255)
    );

  2. Inyecte su DataSource, authenticationManager, UserDetailsService dentro de su OthorizationServer


    @Autowired
    private MyUserDetailsService userDetailsService;
    @Inject
    private AuthenticationManager authenticationManager;
    @Autowired
    private DataSource dataSource;

  3. Necesitarás crear estos dos frijoles

    @Bean
    public JdbcTokenStore tokenStore() {
    return new JdbcTokenStore(dataSource);
    }
    @Bean
    protected AuthorizationCodeServices authorizationCodeServices() {
    return new JdbcAuthorizationCodeServices(dataSource);
    }

    y no se olvide de @Configuration en la parte superior de su clase AuthorizationServer

  4. Configure las aplicaciones de sus clientes para que se creen en su base de datos mysql: clients.jdbc(dataSource).withClient("clientapp")
    .authorizedGrantTypes("password", "refresh_token")
    .authorities("USER")
    .scopes("read", "write")
    .resourceIds(RESOURCE_ID)
    .secret("123456");

    ya has hecho esto.

  5. lo más importante (y creo que lo olvidó ..) es: configurar sus puntos finales con AuthorizationServerEndpointsConfigurer:

    endpoints.userDetailsService(userDetailsService) .authorizationCodeServices(authorizationCodeServices()).authenticationManager(this.authenticationManager).tokenStore(tokenStore()).approvalStoreDisabled();

y eso es todo hombre, ahora debería funcionar;)

Y siéntete libre de pedir más … estaré feliz de ayudarte

¡Te he enviado un mensaje de tweeter!

Esta pregunta es bastante antigua, pero ninguna de las respuestas dio una respuesta al problema original del interrogador. Me encontré con el mismo problema mientras me familiarizaba con la implementación de oauth2 de Spring y me preguntaba por qué el ClientDetailsServiceConfigurer no persiste los clientes que se agregaron mediante programación a través del JdbcClientDetailsServiceBuilder (que se instancia llamando al jdbc(datasource) en el configurador), a pesar de que todos los tutoriales en la red mostraron un ejemplo similar como el publicado por Wim. Después de profundizar en el código, me di cuenta de la razón. Bueno, es simplemente porque el código para actualizar el oauth_clients_details la tabla nunca se llama. Lo que falta es la siguiente llamada después de configurar todos los clientes: .and().build(). Entonces, el código de Wim debe tener el siguiente aspecto:

clients.jdbc(dataSource).withClient("clientapp")
           .authorizedGrantTypes("password", "refresh_token")
           .authorities("USER")
           .scopes("read", "write")
           .resourceIds(RESOURCE_ID)
           .secret("123456").and().build();

Et voila, el cliente clientapp ahora se conserva en la base de datos.

La respuesta de @AndroidLover es buena, pero podría simplificarse. No es necesario crear tablas como oauth_access_token, oauth_refresh_token, etc. a menos que necesite una tienda de tokens jdbc.

Dado que solo necesita un servicio de detalle de cliente jdbc, todo lo que necesita hacer es:

1. crear una tabla de detalles del cliente oauth_client_details, por ejemplo:

drop table if exists oauth_client_details;
    create table oauth_client_details (
    client_id VARCHAR(255) PRIMARY KEY,
    resource_ids VARCHAR(255),
    client_secret VARCHAR(255),
    scope VARCHAR(255),
    authorized_grant_types VARCHAR(255),
    web_server_redirect_uri VARCHAR(255),
    authorities VARCHAR(255),
    access_token_validity INTEGER,
    refresh_token_validity INTEGER,
    additional_information VARCHAR(4096),
    autoapprove VARCHAR(255)
    );

2. cree un modelo de usuario que implemente la interfaz UserDetail, por ejemplo (estoy usando Spring jpa en este caso, podría usar mybatis, jdbc, lo que sea):

@Entity
@Table(name = "users")
public class User implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id", nullable = false, updatable = false)
private String id;

@Column(name = "username", nullable = false, unique = true)
private String username;

@Column(name = "password", nullable = false)
private String password;

@Column(name = "enabled", nullable = false)
@Type(type = "org.hibernate.type.NumericBooleanType")
private boolean enabled;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public void setUsername(String username) {
    this.username = username;
}

public void setPassword(String password) {
    this.password = password;
}

public void setEnabled(boolean enabled) {
    this.enabled = enabled;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add((GrantedAuthority) () -> "ROLE_USER");
    return authorities;
}

@Override
public String getPassword() {
    return this.password;
}

@Override
public String getUsername() {
    return this.username;
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
    public boolean isEnabled() {
        return this.enabled;
    }
}

3. crear un servicio de detalle de usuario personalizado. observe que en su implementación, debe inyectar su servicio dao (en mi caso, inyecté un jpaRepository.) y su servicio dao DEBE tener un método para encontrar usuario por nombre de usuario .:

@Service("userDetailsService")
public class UserService implements UserDetailsService {

@Autowired
UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String userName) throws 
UsernameNotFoundException {
    return userRepository.findByUsername(userName);
}
}

4. finalmente, configure su servidor de autenticación:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired
@Qualifier("dataSource")
DataSource dataSource;

@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;


@Autowired
private AuthenticationManager authenticationManager;

@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) {
    configurer
            .authenticationManager(authenticationManager)                
            .approvalStoreDisabled()
            .userDetailsService(userDetailsService);
}


@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
{
    clients
            .jdbc(dataSource)
            .inMemory().withClient("my-trusted-
client").secret("secret").accessTokenValiditySeconds(3600)
            .scopes("read", "write").authorizedGrantTypes("password", 
"refresh_token").resourceIds("resource");
}
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *