一、报错提示
SpringSecurity提示如下内容:
2023-01-07 06:08:51.843 [cdi-ids-commonprovider] [http-nio-9092-exec-14]
WARN com.desaysv.tsp.logic.ids.config.MyAuthenticationEntryPoint -
登录失败:Full authentication is required to access this resource
二、排查问题
2.1 前端排查
先看前端配置,没有什么问题的感觉?
前端,匹配所有的api 前缀并进行替换为 ’ ’
然后将请求转发到后端localhost端口号为9092的服务
2.2 接口层面排查
请求网址为以下截图,
请求的网址为/api/get-validate-code
没错,我就是要调用的是这个/get-validate-code
2.3后端服务排查
2.2.1检查验证码的拦截器
OncePerRequestFilter是Spring Boot里面的一个过滤器抽象类,
OncePerRequestFilter在Spring Security里面被广泛用到,
OncePerRequestFilter过滤器抽象类通常被用于继承实现并在每次请求时只执行一次过滤。
@Component
public class ValidateCodeFilter extends OncePerRequestFilter {
// spring的正则匹配
private static final PathMatcher pathMatcher = new AntPathMatcher();
@Autowired
private MyAuthenticationFailureHandler authenticationFailureHandler;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 只有登录请求‘/login’,并且为'post'请求时,才校验
if ("POST".equals(request.getMethod())
&& pathMatcher.match("/login", request.getServletPath())) {
try {
codeValidate(request);
} catch (ValidateCodeException e) {
// 验证码不通过,跳到错误处理器处理
authenticationFailureHandler.onAuthenticationFailure(request, response, e);
// 异常后,不执行后面
return;
}
}
doFilter(request, response, filterChain);
}
2.2.1进行接口断点
其中,接口在访问此处时候,可以看拦截请求,我们看拦截的接口的URL,诶?
怎么会有/api的前缀的呢?这个不是我想的呀
2.2.2 看看获取验证码的逻辑
此处是我获取拦截器的逻辑,看起来也没有什么毛病啊?
@Controller
public class ValidateCodeController {
@Autowired
private ValidateCodeCreateService validateCodeCreateService;
@GetMapping("/get-validate-code")
public void getImageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 创建验证码
ValidateCode validateCode = validateCodeCreateService.createImageCode();
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
// 将验证码放到session中(推荐放在Redis中,可设置过期时间能自动删除)
request.getSession().setAttribute("validate-code", validateCode);
// 返回验证码给前端
ImageIO.write(validateCode.getImage(), "JPEG", response.getOutputStream());
}
}
2.2.3 检查SpringSecurity配置文件
既然是SpringSecurity配置文件,那肯定要看SpringSecurityConfig文件
@Override
protected void configure(HttpSecurity http) throws Exception {
// Spring Boot不允许加载iframe问题解决
http.headers().frameOptions().disable();
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 后台验证码
// .addFilterAfter(myLogoutFilter,UsernamePasswordAuthenticationFilter.class)
.csrf().disable().authorizeRequests()
.antMatchers(
"/static/**",
"/session/invalid",
"/clb-health",
"/getAllModel/**",
"/getVoiceServiceModel/**",
"/login/**",
"/logout/**",
"/modifyPassword/**",
"/instances",
"/actuator/**",
"/get-validate-code",
"/etm/**",
"/loginOrLogout/**")
.permitAll().anyRequest().authenticated()
.and().logout().logoutSuccessHandler(logoutSuccessHandler).deleteCookies("JSESSIONID")
.and().formLogin().permitAll()
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
.and().exceptionHandling().authenticationEntryPoint(myAuthenticationEntryPoint);
}
SpringSecurityConfig文件显示,放行所有的 “/get-validate-code”,但是没有说要放行/api/get-validate-code
于是锁定问题肯定是前端的问题了。为啥要把/api传过来呢?
2.4 再次前端排查
(1)尝试修改target的URL
即由原来的
target: 'http://localhost:9092/api/',
修改为
target: 'http://localhost:9092/',
记得重启前端服务哦,不会热启动的。
(2)验证
发现正常获取到验证码了。并且能正常进行登录了
2.5 那为什么要进行API的改写呢?
是不是失效了呢?这个问题有待深入了解,先这样!问题解决了就好