shiro ajax跨域,shiro学习分享(三)——解决跨域问题时遇到的坑

本文介绍了在SpringBoot中整合Shiro框架时遇到的跨域问题,重点讲述了如何通过自定义UserFilter解决OPTIONS请求验证问题,以及如何调整Shiro权限控制以配合前端复杂请求。作者分享了配置CORS和自定义filter的代码示例,以及注意事项和替代方案。
摘要由CSDN通过智能技术生成

shiro学习分享(三)——解决跨域问题时遇到的坑

发布时间:2018-04-21 11:07,

浏览次数:1977

, 标签:

shiro

跨域问题的解决

使用springboot整合了shiro框架,springboot解决跨域的方法也是网上的到处都是的配置CORS解决跨域问题。

出现的问题:

使用了shiro框架,开启了shiro的登陆验证过滤器时,即filterChainDefinitionMap.put("/**","user");

,代表要登陆过才能进行访问,但是经过一番测试,发现当ajax请求为复杂请求时,cookie无法被携带传输到服务器的,导致一直无法访问。

在网上找了很久,大部分网友说复杂请求时若要带cookie则allowedOrigins

不能配置为“*”,而要是访问的地址,虽然可以通过配置过滤器来实现,当是本地的html还是访问不了,一直报跨域错误,而布置在不同端口的html虽然能够访问,当是cookie依旧传不了。。。

最后发现之所以传不了cookie是因为shiro的权限控制,由于复杂请求要传两次,第一次验证请求(OPTIONS

)是没有带cookie的所以验证不通过,导致接下来的真实请求无法继续,因为上面的请求被拒绝了啊。。。

解决思路:

1.可以自定义shiro的UserFilter来让OPTIONS请求无条件通过(shiro的自带的fliter都是可以通过继承来进行重写)

样例如下:

/** * 重写shiro的UserFilter,实现通过OPTIONS请求 * @author MDY */ public class

ShiroUserFilter extends UserFilter { /** * 在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true

*/ @Override protected boolean preHandle(ServletRequest request,

ServletResponse response) throws Exception { HttpServletResponse httpResponse =

(HttpServletResponse) response; HttpServletRequest httpRequest = (

HttpServletRequest) request; if (httpRequest.getMethod().equals(RequestMethod.

OPTIONS.name())) { setHeader(httpRequest,httpResponse); return true; } return

super.preHandle(request,response); } /** * 该方法会在验证失败后调用,这里由于是前后端分离,后台不控制页面跳转 *

因此重写改成传输JSON数据 */ @Override protected void saveRequestAndRedirectToLogin(

ServletRequest request, ServletResponse response) throws IOException {

saveRequest(request); setHeader((HttpServletRequest) request,(

HttpServletResponse) response); PrintWriter out = response.getWriter(); out.

println(JSONObject.toJSONString(ResultUtil.error(ExceptionEnum.IS_NOT_LOGIN)));

out.flush(); out.close(); } /** * 为response设置header,实现跨域 */ private void

setHeader(HttpServletRequest request,HttpServletResponse response){

//跨域的header设置 response.setHeader("Access-control-Allow-Origin", request.

getHeader("Origin")); response.setHeader("Access-Control-Allow-Methods", request

.getMethod()); response.setHeader("Access-Control-Allow-Credentials", "true");

response.setHeader("Access-Control-Allow-Headers", request.getHeader(

"Access-Control-Request-Headers")); //防止乱码,适用于传输JSON数据 response.setHeader(

"Content-Type","application/json;charset=UTF-8"); response.setStatus(HttpStatus.

OK.value()); } }

2.由于博主的项目是不怎么用得到权限控制,shiro关于url的权限控制可有可无,所以博主干脆把

filterChainDefinitionMap.put("/**","user");去掉,这样子所有人都能访问。

但是如果你使用了shiro的其它url权限控制,如身份验证之类的以及shiro的权限控制注解,如果你没有登陆则会抛出

UnauthenticatedException

异常,这时可以使用全局异常控制捕获该异常,将出错信息传回前端,虽然这样子解决不是很优雅。。。(关于全局异常处理网上也有很多教程,也可以看这篇

)

最后附上在网上找到的springboot解决跨域问题的代码

/** * 解决跨域问题springboot所需配置 */ @Configuration public class CORSConfiguration {

@Bean public WebMvcConfigurer CORSConfigurer() { return new

WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry

registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*")

.allowedHeaders("*") //设置是否允许跨域传cookie .allowCredentials(true) //设置缓存时间,减少重复响应 .

maxAge(3600); } }; } }

PS:博主发现sprinboot配置之后前端不用特殊的配置就能进行跨域,不知是不是浏览器的问题还是,但为了保险起见,ajax请求时还是加上

crossDomain:true,xhrFields: { withCredentials: true },

比较好。如果要带上cookie跨域,则必须加上上面两句。

请求样例:

$.ajax({ async:true, type:"post", url:"", data:JSON.stringify(params),

contentType: "application/json; charset=utf-8", crossDomain:true, xhrFields: {

withCredentials: true }, dataType:"json", success:function(data){ console.log(

params); console.log(data); }, error:function(data){ console.log(data) } })

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值