response.isCommitted()

本文详细介绍了HelloServlet类中service()方法的工作流程,包括如何通过PrintWriter对象进行输出及关闭输出流的过程。此外还提到了在关闭输出流前后response.isCommitted()方法返回值的变化情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HelloServlet类的service()方法最后调用PrintWriter对象的close()方法关闭底层输出流,该方法在关闭输出流之前会先把缓冲区内的数据提交到客户端。因此在调用PrintWriter 对象的 close()方法之前,response.isCommitted()方法返回 false;而在调用PrintWriter对象的close()方法之后,response.isCommitted()方法返回true。HelloServlet类的service()方法中的“System.out.println(…)”语句把内容打印到Tomcat服务器所在的控制台。
package com.kucun.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; // 2. 基础安全配置 @Configuration @EnableWebSecurity // 启用Web安全功能 public class SecurityConfig extends WebSecurityConfigurerAdapter{ /** * 核心安全过滤器链配置 * @param http HTTP安全构建器 * @return 安全过滤器链 * @throws Exception 配置异常 * * █ 配置逻辑说明: * 1. authorizeHttpRequests: 定义访问控制规则 * 2. formLogin: 配置表单登录 * 3. logout: 配置注销行为 * 4. exceptionHandling: 处理权限异常[^3] */ @Override public void configure(HttpSecurity http) throws Exception { http .authorizeRequests(auth -> auth // 按从具体到泛型的顺序配置 .antMatchers("/login.html").permitAll() .antMatchers(HttpMethod.POST, "/users/login").permitAll() .antMatchers("/users/guanli/**").hasRole("ADMIN") .antMatchers("/js/**", "/css/**", "/fonts/**", "/images/**").permitAll() .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login.html") .loginProcessingUrl("/users/login") .defaultSuccessUrl("/index.html", true) .failureUrl("/login.html?error=true") ) .logout(logout -> logout .logoutUrl("/logout") .logoutSuccessUrl("/login.html") ) .csrf(csrf -> csrf .ignoringAntMatchers("/users/login") // 禁用CSRF保护 ) .headers(headers -> headers .frameOptions().sameOrigin() ) // 异常处理 .exceptionHandling(ex -> ex .accessDeniedPage("/error/403") // 权限不足跳转页面[^3] ); //return http.build(); } /** * 密码编码器(必须配置) * 使用BCrypt强哈希算法加密 */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AccessDeniedHandler accessDeniedHandler() { System.out.println("0000"); return (request, response, accessDeniedException) -> { if (!response.isCommitted()) { request.getRequestDispatcher("/error/403").forward(request, response); } }; } }
05-29
package com.kucun.Config; import java.io.IOException; import java.io.InputStream; import java.util.Map; import javax.servlet.Filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import com.fasterxml.jackson.databind.ObjectMapper; // 2. 基础安全配置 @Configuration @EnableWebSecurity // 启用Web安全功能 public class SecurityConfig extends WebSecurityConfigurerAdapter{ /** * 核心安全过滤器链配置 * @param http HTTP安全构建器 * @return 安全过滤器链 * @throws Exception 配置异常 * * █ 配置逻辑说明: * 1. authorizeHttpRequests: 定义访问控制规则 * 2. formLogin: 配置表单登录 * 3. logout: 配置注销行为 * 4. exceptionHandling: 处理权限异常[^3] */ // 修正后的配置方法 @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .addFilterBefore(jsonAuthFilter(), UsernamePasswordAuthenticationFilter.class) // 关键配置 .authorizeRequests() .antMatchers("/login.html").permitAll() .antMatchers(HttpMethod.POST, "/users/login").permitAll() .antMatchers("/users/guanli/**").hasAuthority("ROLE_ADMIN") .antMatchers("/js/**", "/css/**", "/fonts/**", "/images/**","/*").permitAll() .anyRequest().authenticated() .and() .formLogin().disable() // .loginPage("/login.html") // .loginProcessingUrl("/users/login") // // .successHandler(ajaxAuthenticationSuccessHandler()) // 自定义成功处理器 // .failureHandler(ajaxAuthenticationFailureHandler()) // 自定义失败处理器 // .defaultSuccessUrl("/index.html") // .failureUrl("/login.html?error=true") // .usernameParameter("andy") // 修改用户名参数名 // .passwordParameter("pass") // 修改密码参数名 // .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login.html") .and() .csrf() .ignoringAntMatchers("/users/login") .and() .headers() .frameOptions().sameOrigin() .and() .exceptionHandling() .accessDeniedHandler(accessDeniedHandler()); // 统一使用Handler } // 返回JSON格式的成功响应 @Bean public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() { return (request, response, authentication) -> { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpStatus.OK.value()); System.out.println(HttpStatus.OK.value()); if (request.getHeader("X-Requested-With") == null) { // 非AJAX请求 response.sendRedirect("/index.html"); } else { response.getWriter().write("{\"status\":\"success\"}"); } }; } // 返回401状态码和错误信息 @Bean public AuthenticationFailureHandler ajaxAuthenticationFailureHandler() { return (request, response, exception) -> { if (request.getHeader("X-Requested-With") == null) { response.sendRedirect("/login.html?error=true"); } else { response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.getWriter().write("{\"error\":\"Authentication failed\"}"); } }; } // 处理未认证请求 @Bean public AuthenticationEntryPoint ajaxAuthenticationEntryPoint() { return (request, response, exception) -> { if (request.getHeader("X-Requested-With") == null) { response.sendRedirect("/login.html?error=true"); } else { response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.getWriter().write("{\"error\":\"Authentication failed\"}"); } }; } @Bean public JsonUsernamePasswordAuthenticationFilter jsonAuthFilter() throws Exception { JsonUsernamePasswordAuthenticationFilter filter = new JsonUsernamePasswordAuthenticationFilter(); filter.setAuthenticationManager(authenticationManagerBean()); filter.setUsernameParameter("andy"); // 设置自定义参数名 filter.setPasswordParameter("pass"); filter.setFilterProcessesUrl("/users/login"); filter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler()); filter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler()); return filter; } /** * 密码编码器(必须配置) * 使用BCrypt强哈希算法加密 */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AccessDeniedHandler accessDeniedHandler() { System.out.println("0000"); return (request, response, ex) -> { if (!response.isCommitted()) { response.sendRedirect("/error/403"); } }; } } class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { System.out.println("收到认证请求,路径:" + request.getRequestURI()); System.out.println("请求方法:" + request.getMethod()); System.out.println("Content-Type:" + request.getContentType()); if (request.getContentType() != null && request.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) { try (InputStream is = request.getInputStream()) { Map<String, String> authMap = objectMapper.readValue(is, Map.class); String username = authMap.getOrDefault(getUsernameParameter(), ""); String password = authMap.getOrDefault(getPasswordParameter(), ""); // 调试日志 System.out.println("Authentication attempt with: " + username+'_'+ password); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } catch (IOException e) { throw new AuthenticationServiceException("认证请求解析失败", e); } } return super.attemptAuthentication(request, response); } } 重定向登录界面没有了
最新发布
05-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值