example ejemplo basada autenticacion java spring-security

java - ejemplo - spring rest jwt authentication example



Autenticación basada en token de seguridad de Spring (2)

Aquí es cómo pude implementar la autenticación basada en token y la autenticación básica

SpringSecurityConfig.java

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(final AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(this.participantService).passwordEncoder(this.passwordEncoder()); } @Override protected void configure(final HttpSecurity http) throws Exception { //Implementing Token based authentication in this filter final TokenAuthenticationFilter tokenFilter = new TokenAuthenticationFilter(); http.addFilterBefore(tokenFilter, BasicAuthenticationFilter.class); //Creating token when basic authentication is successful and the same token can be used to authenticate for further requests final CustomBasicAuthenticationFilter customBasicAuthFilter = new CustomBasicAuthenticationFilter(this.authenticationManager() ); http.addFilter(customBasicAuthFilter); } }

TokenAuthenticationFilter.java

public class TokenAuthenticationFilter extends GenericFilterBean { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest httpRequest = (HttpServletRequest)request; //extract token from header final String accessToken = httpRequest.getHeader("header-name"); if (null != accessToken) { //get and check whether token is valid ( from DB or file wherever you are storing the token) //Populate SecurityContextHolder by fetching relevant information using token final User user = new User( "username", "password", true, true, true, true, authorities); final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } chain.doFilter(request, response); } }

CustomBasicAuthenticationFilter.java

@Component public class CustomBasicAuthenticationFilter extends BasicAuthenticationFilter { @Autowired public CustomBasicAuthenticationFilter(final AuthenticationManager authenticationManager) { super(authenticationManager); } @Override protected void onSuccessfulAuthentication(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response, final Authentication authResult) { //Generate Token //Save the token for the logged in user //send token in the response response.setHeader("header-name" , "token"); } }

Como nuestro CustomBasicAuthenticationFilter se ha configurado y agregado como filtro a la seguridad de Spring,

Siempre que la autenticación básica sea exitosa, la solicitud será redirigida a onSuccessfulAuthentication donde establecemos el token y lo enviamos en la respuesta con algún encabezado "nombre de encabezado".

Si se envía "nombre de encabezado" para una solicitud adicional, la solicitud pasará por TokenAuthenticationFilter primero antes de intentar la autenticación básica.

Tengo una API de descanso en la que me estoy autentificando utilizando la autorización básica de seguridad Spring donde el cliente envía un nombre de usuario y una contraseña para cada solicitud. Ahora, quería implementar la autenticación basada en token donde enviaré un token en el encabezado de respuesta cuando el usuario se autentique al principio. Para solicitudes adicionales, el cliente puede incluir ese token en el encabezado que se usará para autenticar al usuario en los recursos. Tengo dos proveedores de autenticación tokenAuthenticationProvider y daoAuthenticationProvider

@Component public class TokenAuthenticationProvider implements AuthenticationProvider { @Autowired private TokenAuthentcationService service; @Override public Authentication authenticate(final Authentication authentication) throws AuthenticationException { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); final HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); final String token = request.getHeader(Constants.AUTH_HEADER_NAME); final Token tokenObj = this.service.getToken(token); final AuthenticationToken authToken = new AuthenticationToken(tokenObj); return authToken; } @Override public boolean supports(final Class<?> authentication) { return AuthenticationToken.class.isAssignableFrom(authentication); } }

Y en daoAuthenticationProvider, estoy configurando userDetailsService y autentificando contra los detalles de inicio de sesión del usuario al obtenerlo de la base de datos (que funciona bien siempre y cuando el nombre de usuario y la contraseña se utilicen mediante Autorización: Basic bGllQXBpVXNlcjogN21wXidMQRRTTURtR04pag == como cabecera)

Pero cuando incluyo el token en el encabezado con X-AUTH-TOKEN (que es Constants.AUTH_HEADER_NAME), no se llama al tokenAuthenticationProvider. Estoy recibiendo error como

{"timestamp":1487626368308,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/find"}

Y aquí es cómo estoy agregando proveedores de autenticación.

@Override public void configure(final AuthenticationManagerBuilder auth) throws Exception { final UsernamePasswordAuthenticationProvider daoProvider = new UsernamePasswordAuthenticationProvider(this.service, this.passwordEncoder()); auth.authenticationProvider(this.tokenAuthenticationProvider); auth.authenticationProvider(daoProvider); }

Sugiera cómo puedo implementar la autenticación basada en token sin dañar el comportamiento actual de la seguridad Spring.


Puede intentar configurar su token personalizado AuthenticationToken en su filtro de autenticación, por ejemplo:

public class AuthenticationFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { final String authTokenHeader = ((HttpServletRequest)request).getHeader(Constants.AUTH_HEADER_NAME); if (authTokenHeader != null) { SecurityContextHolder.getContext().setAuthentication(createAuthenticationToken(authTokenHeader)); } chain.doFilter( request, response ); } }