Java Spring安全性:使端点控制器仅可通过授权访问:承载令牌头
我试图在没有Java Spring安全性:使端点控制器仅可通过授权访问:承载令牌头,java,spring,spring-boot,spring-mvc,spring-security,Java,Spring,Spring Boot,Spring Mvc,Spring Security,我试图在没有Authorization:Bearer-tokenheader的情况下获取无法访问的端点(503error?) @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.cors().and().csrf().disable() .authorizeRequests()
Authorization:Bearer-token
header的情况下获取无法访问的端点(503
error?)
@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);
}
但是我可以很好地访问它
我应该在配置方法中更改什么
编辑:
@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);
}
}
@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;
}
}
public class SecurityWebApplicationInitializer extends
AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SecurityConfig.class, WebConfig.class);
}
}
似乎jwtRequestFilter
的doFilterInternal
方法从未运行过:我尝试在调试器中设置断点,执行从未停止过
编辑:整个安全配置
:
@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();
}
}
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");
}
}
我设法解决了它。原来问题出在我没有正确的配置上,所以
SecurityConfig
从未应用过。我这样做:
WebConfig.java:
@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);
}
}
@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;
}
}
public class SecurityWebApplicationInitializer extends
AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SecurityConfig.class, WebConfig.class);
}
}
MyAppInitializer.java(注意注释掉的sc.addListener(新的ContextLoaderListener(根));
行,它必须是这样的,否则会有错误-修复是在另一个SO问题中向我建议的):
你能发布更多关于你如何打这个电话的信息吗?另外,您可以发布
jwtRequestFilter
的代码吗?在我的本地机器上运行,我能够在没有附加过滤器的情况下获得所需的403
step@bluesky33我只是向https://localhost:8080/testproject/api/admin/test
端点不带任何headers@bluesky33添加了JwtRequestFilter
它不工作-仍然可以从/api/admin/test
您那里获得响应正在使用两种类型的注入,一种是@Autowired,另一种是构造函数。我尝试了这种方法,但效果很好(也没有使用CORS,即@CrossOrigin)。在上面的类中编辑。也可以在控制器中尝试更改-@GetMapping(“/test”)公共字符串testAdmin(){return“OK;secret test admin”}
它仍然不起作用;(筛选器方法中的代码永远不会运行。