Tengo tres servicios:
Los tres son aplicaciones Spring Boot. La autenticación se realiza a través de la provisión de tokens OAuth2, utilizando el almacén de tokens JDBC. Iniciar sesión, obtener el token funciona bien, solicitar datos de cualquiera de los otros dos servidores de recursos también funciona bien. Sin embargo, no estoy contento con la forma en que lo estoy haciendo, ya que parece un poco torpe:
Todos los datos en los servidores de recursos están vinculados al usuario a través de una ID de usuario generada en el lado del servidor. Creo que vincularlo al nombre de usuario es una mala idea si el usuario alguna vez quiere cambiar su nombre de usuario. En este momento, la forma en que obtengo la ID de usuario es resumida:
@RequestMapping(method = RequestMethod.GET) public ResponseEntity<SampleData> getData(OAuth2Authentication authentication) { Authentication auth = authentication.getUserAuthentication(); final Map<String, Object> map = (Map) auth.getDetails(); // parse user data from the map ... } El método getDetails devuelve el objeto de usuario completo en el servidor de autenticación como un mapa, porque esa es la forma en que lo vinculé en el archivo application.properties :
security.oauth2.resource.userInfoUri=http://localhost:9000/api-auth/userPero no puedo decidirme a estar de acuerdo con esta solución, porque:
OAuth2Authentication authentication como entrada; debería estar en una capa superior y no aquí (aunque podría ser mi sensación equivocada).Mi pregunta es: ¿puedo hacerlo de manera más eficiente? ¿De una forma más limpia y sostenible?
Me gustaría tener:
@RequestMapping(method = RequestMethod.GET) public ResponseEntity<SampleData> getData(String userId) { // interact with data with the userId }Y definitivamente no depende de que el cliente envíe estos datos; esto tiene que provenir del servidor de autenticación.
Mis pensamientos (hasta ahora fallidos):
OncePerRequestFilter y analizo los datos. Pero luego no pude distribuir el objeto analizado directamente en el controlador. Esto parecía ser la solución, pero supongo que no está destinado a esto, tal vez.¿Me estoy acercando a esto completamente mal o me estoy perdiendo algún detalle de Spring Boot que resuelve esto automáticamente?
Usaría la opción 2 con OncePerRequestFilter . Puede analizarlo una vez y almacenar los resultados en ThreadLocal o InheritableThreadLocal si crea nuevos subprocesos.
Luego, se puede acceder a los datos locales del subproceso desde sus controladores o incluso más profundamente desde la capa de servicio.
Cada subproceso contiene una referencia implícita a su copia de una variable local de subproceso siempre que el subproceso esté activo y se pueda acceder a la instancia de ThreadLocal; después de que un subproceso desaparece, todas sus copias de instancias locales de subprocesos están sujetas a recolección de elementos no utilizados (a menos que existan otras referencias a estas copias).