有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaSpring安全性:使端点控制器仅可通过Authorization:Bearer令牌头访问

我试图获取一个不可访问的端点(503错误?)没有Authorization: Bearer token

  @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().and().csrf().disable()
                .authorizeRequests()
                        .antMatchers("/authenticate")
                .permitAll()
              .antMatchers("/api/admin/**")
                .fullyAuthenticated()
                .anyRequest().authenticated().and().
                exceptionHandling()
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests();
        httpSecurity.addFilterBefore(jwtRequestFilter,
                UsernamePasswordAuthenticationFilter.class);
    }
@RestController
@CrossOrigin
@RequestMapping("/api/admin")
public class AdminController {
    @RequestMapping("/test")
    public String testAdmin()  {
        return "OK; secret test admin";
    }
}

但是我可以很好地访问它 我应该在配置方法中更改什么

编辑

@Component
public class JwtRequestFilter extends OncePerRequestFilter {
    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String authorizationHeader = request.getHeader("Authorization");
        String username = null;
        String jwt = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwt);
        }

        if (username != null && SecurityContextHolder
                                .getContext().getAuthentication() == null) {
           
            UserDetails userDetails = this
                    .userDetailsService.loadUserByUsername(username);

          
            if (jwtUtil.validateToken(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken
                        usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }

        chain.doFilter(request, response);
    }
}

似乎jwtRequestFilterdoFilterInternal方法从未运行过:我尝试在调试器中设置断点,执行从未停止过

编辑:整个SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter  {
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtRequestFilter jwtRequestFilter;
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    public SecurityConfig(
            UserDetailsServiceImpl userDetailsService)  {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    DaoAuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider =
                new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(this.userDetailsService);
        return daoAuthenticationProvider;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring();
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
       
        httpSecurity.csrf().disable()
                // dont authenticate this particular request
                .authorizeRequests().antMatchers("/api/login").permitAll()
                // all other requests need to be authenticated
                .anyRequest().authenticated().and()
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // Add a filter to validate the tokens with every request
        httpSecurity.addFilterBefore(jwtRequestFilter,
                UsernamePasswordAuthenticationFilter.class);

    }


    @Bean
    BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

共 (2) 个答案

  1. # 1 楼答案

    我设法解决了。事实证明,问题在于我没有正确的配置,所以SecurityConfig从未被应用。我这样做:

    网络配置。java

    @Configuration
    @ComponentScan("testproject")
    @EnableWebMvc
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = "testproject",
            entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
     public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void configureDefaultServletHandling(
                    DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
        }
    
        @Bean
        public ViewResolver viewResolver() {
            InternalResourceViewResolver bean = new InternalResourceViewResolver();
    
            bean.setViewClass(JstlView.class);
            bean.setPrefix("/WEB-INF/view/");
    bean.setSuffix(".html");
    
    
            return bean;
        }
    
        @Bean
        public UserDetailsService userDetailsService()  {
            UserDetailsService userDetailsService =
                    new UserDetailsServiceImpl();
            return userDetailsService;
        }
    }
    

    MyAppInitializer。java(注意注释掉的sc.addListener(new ContextLoaderListener(root));行,必须是这样的,否则会有错误-修复是在另一个问题中向我建议的):

    public class MyAppInitializer extends
                    AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        public void onStartup(final ServletContext sc) throws ServletException {
            System.out.println("onStartup!");
    
            AnnotationConfigWebApplicationContext root =
                    new AnnotationConfigWebApplicationContext();
    
            root.register(WebConfig.class);
            root.setServletContext(sc);
    
            root.scan("testproject");
            //sc.addListener(new ContextLoaderListener(root));
    
            ServletRegistration.Dynamic appServlet =
                    sc.addServlet("dispatcher", new DispatcherServlet(new GenericWebApplicationContext()));
            appServlet.setLoadOnStartup(1);
            appServlet.addMapping("/");
        }
    
            @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] {SecurityConfig.class};
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{WebConfig.class};
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    }
    

    SecurityWebApplicationInitializer。java

    public class SecurityWebApplicationInitializer extends
                        AbstractSecurityWebApplicationInitializer {
        public SecurityWebApplicationInitializer() {
            super(SecurityConfig.class, WebConfig.class);
        }
    }
    
  2. # 2 楼答案

    HTTP响应503表示服务不可用。当令牌丢失时,您应该获得401授权

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
      @Autowired
      private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    
      @Autowired
      private UserDetailsService jwtUserDetailsService;
    
      @Autowired
      private JwtRequestFilter jwtRequestFilter;
    
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {    
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
      }
    
      @Bean
      public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
      }
    
      @Bean
      @Override
      public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
      }
    
      @Override
      protected void configure(HttpSecurity httpSecurity) throws Exception {    
        httpSecurity.csrf().disable()
            // dont authenticate this particular request
            .authorizeRequests().antMatchers("/login").permitAll()        
            // all other requests need to be authenticated
            .anyRequest().authenticated().and()        
            .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
        // Add a filter to validate the tokens with every request
        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
      }
    }
    

    使用AuthenticationEntryPoint

    @Component
    public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
      
      private static final long serialVersionUID = -1L;
      
      @Override
      public void commence(HttpServletRequest request, 
          HttpServletResponse response,
          AuthenticationException authException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
      }
    }