Spring Security using HTTP headers

前端 未结 4 916
青春惊慌失措
青春惊慌失措 2021-02-14 12:05

I am trying to add security to my Spring Boot application. My current application is using REST controllers and every time I get a GET or POST request

相关标签:
4条回答
  • 2021-02-14 12:52

    In spring boot app you can add below to application.properties

    security.user.name=user
    security.user.password=password
    

    It will do rest of the thing like getting it from header and validation for more visit https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html

    0 讨论(0)
  • 2021-02-14 13:01

    the minimal code addition is to define a filter and add it to the security configuration, smth like

    XHeaderAuthenticationFilter.java

    @Component
    public class XHeaderAuthenticationFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
    
        String xAuth = request.getHeader("X-Authorization");
    
        User user = findByToken(xAuth);
    
        if (user == null) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token invalid");
        } else {
            final UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
    
            filterChain.doFilter(request, response);
        }
    }
    
    //need to implement db user validation...
    private User findByToken(String token) {
        if (!token.equals("1234"))
            return null;
    
        final User user = new User(
                "username",
                "password",
                true,
                true,
                true,
                true,
                Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
    
        return user;
    }
    }
    

    SecurityConfig.java

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(final HttpSecurity http) throws Exception {
            http.sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .exceptionHandling()
                    .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                .and()
                .addFilterBefore(new XHeaderAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    }
    

    another approach is to use spring's AOP to define annotation of some logic to perform before entering the annotated controller method

    0 讨论(0)
  • 2021-02-14 13:01

    In memory authentication would serve your purpose

    @Configuration
    @EnableWebMvc
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
            .withUser("user1").password("password1").roles("USER")
            .and()
            .withUser("user2").password("password2").roles("ADMIN");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().fullyAuthenticated();
            http.httpBasic();   
        }
    
    }
    
    0 讨论(0)
  • 2021-02-14 13:07

    You should avoid using default org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter since it gets client supplied username and password from the parameters of your request and you really need to get them from the headers.

    So, you should write a custom AuthenticationFilter extending referred UsernamePasswordAuthenticationFilter to change its behaviour to fit your requirements:

    public class HeaderUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    
      public HeaderUsernamePasswordAuthenticationFilter() {
        super();
        this.setFilterProcessesUrl("/**");
        this.setPostOnly(false);
      }
    
      /* (non-Javadoc)
       * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainPassword(javax.servlet.http.HttpServletRequest)
       */
      @Override
      protected String obtainPassword(HttpServletRequest request) {
        return request.getHeader(this.getPasswordParameter());
      }
    
      /* (non-Javadoc)
       * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainUsername(javax.servlet.http.HttpServletRequest)
       */
      @Override
      protected String obtainUsername(HttpServletRequest request) {
        return request.getHeader(this.getPasswordParameter());
      }
    
    }
    

    This filter example extends org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter listens to every request and gets username and password from headers instead of parameters.

    Then you should change the configuration this way, setting your filter in the UsernamePasswordAuthenticationFilter position:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAt(
                    new HeaderUsernamePasswordAuthenticationFilter(), 
                    UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/index.html").permitAll()
                .antMatchers("/swagger-ui.html").hasRole("ADMIN")
                .anyRequest().authenticated();
    
    }
    
    0 讨论(0)
提交回复
热议问题