usernamepasswordauthenticationtoken providers multiple manager example custom java spring spring-mvc spring-security

java - providers - spring security oauth2



Autenticación personalizada de Spring Security: AuthenticationProvider vs UserDetailsService (3)

Desde la documentación de seguridad de Spring, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture

A menudo hay alguna confusión acerca de UserDetailsService. Es puramente un DAO para los datos del usuario y no realiza otra función que no sea suministrar esos datos a otros componentes dentro del marco. En particular, no autentica al usuario, lo cual es realizado por el AuthenticationManager. En muchos casos, tiene más sentido implementar AuthenticationProvider directamente si necesita un proceso de autenticación personalizado.

AuthenticationProvider y UserDetailsService tienen un propósito diferente.

AuthenticationProvider autentica (compara) el usuario (solicitud) proporcionado el nombre de usuario y la contraseña con el usuario del sistema (puede ser cualquier sistema como DB que mantiene la lista de usuarios registrados)

Es responsabilidad de la implementación del Servicio de Detalles del Usuario obtener los Detalles del Usuario del Sistema que coincidan con el Nombre de Usuario proporcionado por el usuario. Aquí solo obtiene los usuarios que tienen el mismo nombre de usuario y no le dice a la aplicación si la autenticación es exitosa o no.

Ejemplo: Spring proporciona lo siguiente como una configuración predeterminada para autenticar los detalles de un usuario en la base de datos

  • AuthenticationProvider - DaoAuthenticationProvider que extiende AbstractUserDetailsAuthenticationProvider que llama al método de autenticación al pasar el nombre de usuario, objeto de autenticación
  • UserDetailsService - JdbcDaoImpl
  • Flujo de autentificación
  1. La responsabilidad de DaoAuthenticationProvider es autenticar el nombre de usuario y la contraseña obtenidos de la solicitud con el usuario de la base de datos.
  2. Para obtener el usuario de la base de datos correspondiente, le pide a UserDetailsService Implementataion JdbcDaoImpl que obtenga un objeto UserDetail de la base de datos con el mismo nombre que el nombre de usuario de solicitud. Aquí JdbcDaoImpl simplemente obtiene el objeto UserDetails del sistema. ese usuario no se encuentra.
  3. Si los detalles del usuario se encuentran en la base de datos, DaoAuthenticationProvider continúa con la verificación de la contraseña de usuario solicitada con la contraseña de usuario encontrada en el DB; de lo contrario, la autenticación falla.
  4. DaoAuthenticationProvider responderá si el usuario está autenticado o no en función de la respuesta JdbcDaoImpl.

Echa un vistazo aquí para entenderlo mejor:

AuthenticationProvider - DaoAuthenticationProvider extiende AbstractUserDetailsAuthenticationProvider

UserDetailsService - JdbcDaoImpl

Detalles del User - User

Hasta donde puedo entender, cuando desee una autenticación personalizada en Spring Security, puede implementar un UserDetailsService AuthenticationProvider personalizado o un UserDetailsService personalizado UserDetailsService .

@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth //.authenticationProvider(authProvider) // option 1 .userDetailsService(userDetailsService); // option 2 }

En el proveedor de autenticación, puede verificar el nombre de usuario y la contraseña y devolver la Authentication con su objeto personalizado.

public Authentication authenticate(Authentication authentication){ if (checkUsernameAndPassword(authentication)) { CustomUserDetails userDetails = new CustomUserDetails(); //add whatever you want to the custom user details object return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths); } else { throw new BadCredentialsException("Unable to auth against third party systems"); } }

En UserDetailsService solo obtiene el nombre de usuario y cuando devuelve UserDeatails personalizados, el marco realiza una comprobación de la contraseña.

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { CustomUserDetails user = new CustomUserDetails(); //add whatever you want to the custom user details object return user; }

Parece que ambos pueden producir resultados similares. Entonces la pregunta es ¿cuál es la diferencia? ¿Cuándo al usuario uno frente al otro?


Esos dos están relacionados pero están separados intencionalmente por Spring Security. Si la empresa tiene varios sistemas, UserDetailsService proporcionará la información específica del usuario que posee su sistema en particular, aunque la autenticación PUEDE ser realizada por otro sistema. En un sistema simple, se pueden combinar. Por ejemplo, una llamada a la base de datos verificará el nombre de usuario / contraseña y recuperará todo el correo electrónico, ID y etc. de ese usuario.

Según Spring Security Reference: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#getting-started

A menudo hay alguna confusión acerca de UserDetailsService. Es puramente un DAO para los datos del usuario y no realiza otra función que no sea suministrar esos datos a otros componentes dentro del marco. En particular, no autentica al usuario, lo cual es realizado por el AuthenticationManager. En muchos casos, tiene más sentido implementar AuthenticationProvider directamente si necesita un proceso de autenticación personalizado.


La respuesta está dentro de tu pregunta. cuando está utilizando un sistema de autenticación diferente, y la contraseña no se proporciona en su propia base de datos / modelo de datos, debe utilizar el Proveedor de autenticación. por ejemplo, he trabajado en un proyecto en el que el cliente tenía un sistema de autenticación centralizado (CAS), por lo que mi sistema no tenía idea de la contraseña, tenía que implementar el Proveedor de Autenticación y enviar la contraseña dada al CAS y actuar de acuerdo con a su respuesta.

Pero en otro sistema, estaba almacenando la contraseña en mi base de datos, así que todo lo que tenía que hacer era implementar UserDetailsService y verificar si el usuario existe o no en mi base de datos, Spring-Security tenía que hacer el resto.