Spring Security unexpected behavior for REST endpoints authentication?

前端 未结 6 1536
暖寄归人
暖寄归人 2021-01-15 03:44

The scenario we are looking for is as follows:

  1. client connects with REST to a REST login url
  2. Spring microservice (using Spring Security) should return
6条回答
  •  再見小時候
    2021-01-15 04:01

    If you need a rest api, you must not use http.formLogin(). It generates form based login as described here.

    Instead you can have this configuration

    httpSecurity
                    .csrf()
                        .disable()
                    .exceptionHandling()
                        .authenticationEntryPoint(authenticationEntryPoint)
                    .and()
                    .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        .antMatchers("/login").permitAll()
                        .anyRequest().authenticated()
                    .and()
                    .logout()
                        .disable()
                    .addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class);
    

    Create a class, AuthTokenFilter which extends Spring UsernamePasswordAuthenticationFilter and override doFilter method, which checks for an authentication token in every request and sets SecurityContextHolder accordingly.

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletResponse resp = (HttpServletResponse) response;
            resp.setHeader("Access-Control-Allow-Origin", "*");
            resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
            resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, " + tokenHeader);
    
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String authToken = httpRequest.getHeader(tokenHeader);
            String username = this.tokenUtils.getUsernameFromToken(authToken); // Create some token utility class to manage tokens
    
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
    
                UsernamePasswordAuthenticationToken authentication =
                                new UsernamePasswordAuthenticationToken(-------------);
                // Create an authnetication as above and set SecurityContextHolder
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
            SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            chain.doFilter(request, response);
    }
    

    Then create an AuthenticationController, mapped with /login url, which checks credentials, and returns token.

    /*
    * Perform the authentication. This will call Spring UserDetailsService's loadUserByUsername implicitly
    * BadCredentialsException is thrown if username and password mismatch
    */
    Authentication authentication = this.authenticationManager.authenticate(
         new UsernamePasswordAuthenticationToken(
                authenticationRequest.getUsername(),
                authenticationRequest.getPassword()
         )
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);        
    UserDetailsImp userDetails = (UserDetailsImp) authentication.getPrincipal();
    // Generate token using some Token Utils class methods, using this principal
    

    To understand loadUserByUsername , UserDetailsService and UserDetails, please refer Spring security docs }

    For better understanding, please thoroughly read above link and subsequent chapters.

提交回复
热议问题