社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
主要问题:针对前后端分离后,前端使用ajax进行请求,存在一些跨域的问题。
后端对跨域的问题进行解决,因为我是使用的Springboot框架做的后端,首先解决普通请求跨域的问题
@CrossOrigin
每一个controller类上需要添加CrossOrigin的注解进行处理。
添加之后在使用SpringSecurity时允许匿名访问的接口都没有跨域的问题了,不过使用JWT对用户身份进行验证时虽然前端已经将token的值添加到了header中,还是值获取不到header中的token值。
关键的问题就是在这里:
浏览器会在ajax发送请求之前发送一个预请求,确认当请的接口是不是有效的接口,此时的请求方式是OPTIONS的请求方式
因为之前一直没有判断是否是预请求,所以security直接将请求的方式做了正常的处理,导致没有获取到token值所以返回的相应一直是401未授权。这时候就看到前端即使是在头部添加了token但是请求接口一直提示身份认证失败。
需要更改JWT过滤器中的对前端请求的处理方式:
@Slf4j public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtTokenUtil jwtTokenUtil; //定义的tokenHeader的名称 private String tokenHeader = "Authorization"; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { if (request.getMethod().equals("OPTIONS")){ log.info("浏览器的预请求的处理.."); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Authorization,token"); return; }else { String authToken = request.getHeader(this.tokenHeader); String username = jwtTokenUtil.getUsernameFromToken(authToken); log.info("checking authentication for user " + username); //当token中的username不为空是进行验证token是否是有效的token if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { log.info("token中的username不为空,Context中的authentication为空时,进行token的验证.."); //TODO,从数据库得到带有密码的完整user信息 UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); log.info("加载userdetails:{}",userDetails.getUsername()); // For simple validation it is completely sufficient to just check the token integrity. You don't have to call // the database compellingly. Again it's up to you ;) if (jwtTokenUtil.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); log.info("authenticated user " + username + ", setting security context"); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } } }
对第一次的请求进行判断是否是OPTIONS的请求方式,如果是则在对应的response中添加对跨域和header的配置信息
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Authorization,token");
如果不是则进行后面的token验证。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!