tutorial example ejemplo java spring spring-security spring-boot httprequest

java - example - ¿Cómo desactivo la resolución de los parámetros de inicio de sesión pasados como parámetros de url/desde la url?



spring security rest token authentication (4)

La aplicación registra todas las url solicitadas. Esto significa que es fundamental no autenticar el uso de parámetros de url, ya que causaría la situación en la que los registros están llenos de pares (login=abc&password=123) . Por esta razón, he configurado spring-security para leer los parámetros del request-body de la request-body . Se hace agregando la siguiente línea al request-header :

''Content-Type'': ''application/x-www-form-urlencoded''

El cuerpo será:

{''login'':''admin'', ''password'':''password''}

Está bien, pero el control de calidad me obliga a desactivar la posibilidad de autenticación a través de parámetros de URL. En este momento, también se autenticará una POST a la siguiente URL:

https://example.com/foo?login=admin&password=password

¿Alguien sabe un truco para desactivar esta opción? Con una anotación preferiblemente.

Debido al comentario, decidí agregar más detalles a mi problema. Mi spring-security está configurado con WebSecurityConfigurerAdapter . yo tengo

http.usernameParameter("login") .passwordParameter("password") (...)

Esto hace que Spring busque datos de inicio de sesión tanto en parámetros como en cuerpo. Deseo desactivar la búsqueda de esos parámetros en la url.


Esto hace que Spring busque datos de inicio de sesión tanto en parámetros como en cuerpo. Deseo desactivar la búsqueda de esos parámetros en la url.

Creo que esto no es posible ya que este comportamiento no está implementado por Spring en lugar de JavaEE.

HttpServletRequest.getParameter doc states:

Devuelve el valor de un parámetro de solicitud como una cadena o nulo si el parámetro no existe. Los parámetros de solicitud son información adicional enviada con la solicitud. Para los servlets HTTP, los parámetros están contenidos en la cadena de consulta o en los datos del formulario publicado .

Pero puedes intentar alterar esto con un filtro que debería verse más o menos así:

public class DisableGetAuthFiler extends OncePerRequestFilter { ... @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter( new HttpServletRequestWrapper(request) { @Override public String getParameter(String name) { if (("login".equals(name) && getQueryString().contains("login")) || ("password".equals(name) && getQueryString().contains("password"))) { return null; } else { return super.getParameter(name); } } }, response ); } }

EDITAR Haim Raman propuso otra solution que utiliza filtro existente en lugar de introducir uno nuevo. Solo sugiero anular obtainUsername() y obtainPassword() lugar de attemptAuthentication() .


Me gustaría sugerir una alternativa que se base en el evaluador de seguridad de primavera y luego una solución alternativa como lo sugiere el .

Esta respuesta proporciona una solución al problema sugerido por xenteros on bres26 answer también

Reemplazar la implementación de UsernamePasswordAuthenticationFilter que sale

public class ImprovedUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override protected String obtainUsername(HttpServletRequest request) { final String usernameParameter = getUsernameParameter(); validateQueryParameter(request, usernameParameter); return super.obtainUsername(request); } @Override protected String obtainPassword(HttpServletRequest request) { final String passwordParameter = getPasswordParameter(); validateQueryParameter(request, passwordParameter); return super.obtainPassword(request); } private void validateQueryParameter(HttpServletRequest request, String parameter) { final String queryString = request.getQueryString(); if (!StringUtils.isEmpty(queryString)) { if (queryString.contains(parameter)) throw new AuthenticationServiceException("Query parameters for login are a prohibit, use message body only!"); } } }

Necesita reemplazar su propia implementación con la existente (vea el documento here )

@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home","/login").permitAll() .anyRequest().authenticated() .and() .logout() .permitAll() .and() //Replace FORM_LOGIN_FILTER with your own custom implementation .addFilterAt(improvedUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")) .and() //disable csrf to allow easy testing .csrf().disable(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); } public UsernamePasswordAuthenticationFilter improvedUsernamePasswordAuthenticationFilter() throws Exception { UsernamePasswordAuthenticationFilter authFilter = new ImprovedUsernamePasswordAuthenticationFilter(); authFilter.setRequiresAuthenticationRequestMatcher( new AntPathRequestMatcher("/login", "POST") ); authFilter .setAuthenticationManager(authenticationManager()); authFilter .setAuthenticationSuccessHandler( new SavedRequestAwareAuthenticationSuccessHandler() ); authFilter .setAuthenticationFailureHandler( new SimpleUrlAuthenticationFailureHandler("/login?error") ); return authFilter; } }

Ventajas : se basa en la seguridad de primavera y flexible a los cambios.
Desventaja : Desafortunadamente, encontré Spring Java Config muy difícil de configurar y leer

EDITAR: acepté el comentario de chimmi y anulé el nombre de usuario get getConsecuencia
Puedes encontrar el código fuente en github .


Puede lograr esto modificando el RequestMatcher . Por ejemplo:

public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() .withObjectPostProcessor(new ObjectPostProcessor<UsernamePasswordAuthenticationFilter>() { @Override public <O extends UsernamePasswordAuthenticationFilter> O postProcess( O filter) { AntPathRequestMatcher pathMatcher = new AntPathRequestMatcher("/login", "POST"); RequestMatcher noQuery = new RequestMatcher() { @Override public boolean matches(HttpServletRequest request) { return request.getQueryString() == null; } }; AndRequestMatcher matcher = new AndRequestMatcher(Arrays.asList(pathMatcher, noQuery)); filter.setRequiresAuthenticationRequestMatcher(matcher); return filter; } }) .and() ... } }

NOTA : El requisito a continuación no impide que se emita una solicitud GET (y, por lo tanto, filtra las credenciales). Depende realmente de la IU asegurarse de que esto no suceda.

Está bien, pero el control de calidad me obliga a desactivar la posibilidad de autenticación a través de parámetros de URL.


Según mi leal saber y entender, como jhan había mencionado, la solución adecuada sería utilizar la anotación @RequestMapping(value="/login", method="RequestMethod.POST") . Entonces, independientemente de los parámetros que el usuario pueda aprobar con la URL, tanto la URL como el URI siempre serán predeterminados para / iniciar sesión. Y eso es lo que el registrador documentará. No son los pares de nombre de usuario y contraseña, sino "http://localhost:8080/login" , o el puerto que sea.