java - example - Autenticación REST a través de Spring
java swing spring boot (4)
¿Por qué no empiezas a usar OAuth con JSON WebTokens?
http://projects.spring.io/spring-security-oauth/
OAuth2 es un protocolo / marco de autorización estandarizado. Según la Specification oficial de OAuth2:
Puedes encontrar más información here
Problema:
Tenemos una API RESTful basada en Spring MVC que contiene información confidencial. La API debe estar protegida, sin embargo, no es conveniente enviar las credenciales del usuario (combo de usuario / paso) con cada solicitud. Según las pautas de REST (y los requisitos comerciales internos), el servidor debe permanecer sin estado. La API será consumida por otro servidor en un enfoque de estilo mashup.
Requisitos:
El cliente realiza una solicitud para
.../authenticate
(URL desprotegida) con credenciales; el servidor devuelve un token seguro que contiene suficiente información para que el servidor valide las solicitudes futuras y permanezca sin estado. Esto probablemente consistiría en la misma información que el token Recordarme de Spring Security.El cliente realiza solicitudes subsiguientes a varias URL (protegidas), agregando el token previamente obtenido como un parámetro de consulta (o, menos deseablemente, un encabezado de solicitud HTTP).
No se puede esperar que el cliente almacene cookies.
Como ya usamos Spring, la solución debería hacer uso de Spring Security.
Hemos estado golpeando nuestras cabezas contra la pared tratando de hacer que esto funcione, así que espero que alguien haya resuelto este problema.
Dado el escenario anterior, ¿cómo podría resolver esta necesidad particular?
Con respecto a los tokens que contienen información, los tokens web de JSON ( http://jwt.io ) son una tecnología brillante. El concepto principal es incrustar elementos de información (reclamaciones) en el token, y luego firmar todo el token para que el fin de validación pueda verificar que las reclamaciones son realmente confiables.
Yo uso esta implementación de Java: https://bitbucket.org/b_c/jose4j/wiki/Home
También hay un módulo Spring (spring-security-jwt), pero no he investigado qué es lo que soporta.
Conseguimos que esto funcionara exactamente como se describe en el OP, y esperamos que alguien más pueda hacer uso de la solución. Esto es lo que hicimos:
Configure el contexto de seguridad de esta manera:
<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="CustomAuthenticationEntryPoint">
<security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" />
<security:intercept-url pattern="/authenticate" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>
<bean id="CustomAuthenticationEntryPoint"
class="com.demo.api.support.spring.CustomAuthenticationEntryPoint" />
<bean id="authenticationTokenProcessingFilter"
class="com.demo.api.support.spring.AuthenticationTokenProcessingFilter" >
<constructor-arg ref="authenticationManager" />
</bean>
Como puede ver, hemos creado un AuthenticationEntryPoint
personalizado, que básicamente devuelve un 401 Unauthorized
si la solicitud no fue autenticada en la cadena de filtros por nuestro AuthenticationTokenProcessingFilter
.
CustomAuthenticationEntryPoint :
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
}
}
AuthenticationTokenProcessingFilter :
public class AuthenticationTokenProcessingFilter extends GenericFilterBean {
@Autowired UserService userService;
@Autowired TokenUtils tokenUtils;
AuthenticationManager authManager;
public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
this.authManager = authManager;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
@SuppressWarnings("unchecked")
Map<String, String[]> parms = request.getParameterMap();
if(parms.containsKey("token")) {
String token = parms.get("token")[0]; // grab the first "token" parameter
// validate the token
if (tokenUtils.validate(token)) {
// determine the user based on the (already validated) token
UserDetails userDetails = tokenUtils.getUserFromToken(token);
// build an Authentication object with the user''s info
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));
// set the authentication into the SecurityContext
SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication));
}
}
// continue thru the filter chain
chain.doFilter(request, response);
}
}
Obviamente, TokenUtils
contiene algún TokenUtils
privado (y muy específico para cada caso) y no se puede compartir fácilmente. Aquí está su interfaz:
public interface TokenUtils {
String getToken(UserDetails userDetails);
String getToken(UserDetails userDetails, Long expiration);
boolean validate(String token);
UserDetails getUserFromToken(String token);
}
Eso debería hacer que comiences bien. Feliz codificacion :)
Podría considerar la autenticación de acceso de resumen . Esencialmente el protocolo es el siguiente:
- La solicitud se realiza desde el cliente
- El servidor responde con una cadena única de nonce
- El cliente proporciona un nombre de usuario y una contraseña (y algunos otros valores) md5 hash con el nonce; este hash se conoce como HA1
- El servidor puede entonces verificar la identidad del cliente y entregar los materiales solicitados
- La comunicación con el nonce puede continuar hasta que el servidor suministre un nuevo nonce (se utiliza un contador para eliminar los ataques de repetición)
Toda esta comunicación se realiza a través de encabezados, que, como señala jmort253, generalmente es más seguro que comunicar material sensible en los parámetros de url.
La autenticación de acceso implícita es compatible con Spring Security . Tenga en cuenta que, aunque los documentos dicen que debe tener acceso a la contraseña de texto sin formato de su cliente, puede autenticarse con éxito si tiene el hash HA1 para su cliente.