shiro异步请求返回JSON响应

需求1:当shiro请求资源,但是没有进行认证时,默认是进行重定向,现在需要返回JSON响应。注意异步请求,服务器重定向后,ajax拿到的是浏览器重定向后的到的页面源码。
解决2: 自定义FormAuthenticationFilter。覆盖onAccessDenied方法。返回JSON字符串。并将自定义的过滤器添加到ShiroFilterFactoryBean,键的名称为authc。
需求2:ShiroFilterFactoryBean用注解时,过滤的urls被写死在代码中,需要将urls的配置放到配置文件中。
解决2:
方法1:ShiroFilterFactoryBean不使用注解方法,而是xml配置注入。@ImportResource("classpath:shiro/shiro-config.xml")
方法2:自己通过shiro的Ini类加载ini配置文件。读取自定义的urls。

步骤

自定义 authc 对应过滤器 FormAuthenticationFilter。覆盖 onAccessDenied 方法返回JSON响应。

将自定义过滤器添加到 ShiroFilterFactoryBean。名称为 authc 。

ResultFormAuthenticationFilter

package com.mozq.shiro.shiro01.config;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap; @Slf4j
public class ResultFormAuthenticationFilter extends FormAuthenticationFilter { protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
if(isAjaxRequest(request)){
saveRequest(request);
writeResult(response);
return false;
}
//saveRequestAndRedirectToLogin(request, response);
return false;
}
} private boolean isAjaxRequest(ServletRequest request){
return request instanceof HttpServletRequest && "XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest)request).getHeader("X-Requested-With"));
} private void writeResult(ServletResponse servletResponse){
if(servletResponse instanceof HttpServletResponse){
HttpServletResponse response = (HttpServletResponse) servletResponse;
HashMap<String, String> result = new HashMap<>();
result.put("code", "401");
result.put("message","未登录");
try {
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(result));
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.yuantiao.smartcardms.config.shiro;

import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager; import java.util.HashMap;
import java.util.Map; /**
* @description:
* @author: changzhou.xie@yuantiaokj.com
* @date: 2019/11/1 14:14
*/
@Configuration
public class ShiroConfig { //自定义 org.apache.shiro.realm.Realm
@Bean
public Realm realm(){
//IniRealm iniRealm = new IniRealm("classpath:user.ini");
SysUserRealm realm = new SysUserRealm();
return realm;
} //定义 org.apache.shiro.mgt.SecurityManager
@Bean
public SecurityManager securityManager(Realm realm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
} //定义 org.apache.shiro.spring.web.ShiroFilterFactoryBean
/* @Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//过滤的路径
Map<String, String> map = new HashMap<>();
map.put("/**", "authc");
map.put("/user/login/pc", "anon");//放行登录相关接口
shiroFilterFactoryBean.setFilterChainDefinitionMap(map); shiroFilterFactoryBean.setLoginUrl("/login.html");//登录页面
return shiroFilterFactoryBean;
}*/
}

使用配置文件来创建ShiroFilterFactoryBean

package com.yuantiao.smartcardms;

import org.apache.catalina.connector.Connector;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; /**
* SpringBoot项目启动类
*/
@SpringBootApplication
@EnableScheduling/* 开启定时任务 */
@MapperScan("com.yuantiao.smartcardms.dao.mapper")
@ImportResource("classpath:shiro/shiro-config.xml")
public class SmartcardMsApplication { public static void main(String[] args) {
SpringApplication.run(SmartcardMsApplication.class, args);
} /**
* CORS跨域请求解决403
* @return
*/
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
} /**
* 跨域请求COOKIES携带SessionId
* @return
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
} /**
* 请求链接[]{}非法字符
* @return
*/
@Bean
public TomcatServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers((Connector connector) -> {
connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
});
return factory;
} }
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="filterChainDefinitionMap" >
<!-- 用props无法保证资源是按照顺序加载到filterChainDefinitionMap的,会有问题 -->
<!--<props>-->
<!--<prop key="/user/add">anon</prop>-->
<!--<prop key="/user/delete">roles[laoban]</prop>-->
<!--<prop key="/user/login/pc">anon</prop>-->
<!--<prop key="/user/logout">anon</prop>-->
<!--<prop key="/**">authc</prop>-->
<!--</props>-->
<map>
<entry key="/user/login/pc" value="anon"/>
<entry key="/**" value="authc"/>
</map>
</property>
<property name="loginUrl" value="/login.html"/>
<property name="securityManager" ref="securityManager"/>
<property name="filters">
<map>
<entry key="authc">
<bean class="com.yuantiao.smartcardms.config.shiro.ResultFormAuthenticationFilter"/>
</entry>
</map>
</property>
</bean> </beans>

错误

<property name="filterChainDefinitionMap" >
<value>
/card.html = anon
/** = authc
</value>
</property>
<!--
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map' for property 'filterChainDefinitionMap': no matching editors or conversion strategy found 看到网上很多filterChainDefinitionMap这种写,但是一配置直接报错。value指定的是字符串,而filterChainDefinitionMap是一个LinkedHashMap对象。完全无法这样配置。
-->

bugs

jquery-3.1.1.min.js:4 POST http://localhost:9000/smartcard/user/login/pc 415
请求头:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Set-Cookie: JSESSIONID=080D2E469D78CD39C88AE54950B6640D; Path=/smartcard; HttpOnly
Set-Cookie: rememberMe=deleteMe; Path=/smartcard; Max-Age=0; Expires=Sat, 02-Nov-2019 02:32:54 GMT

shiro异步请求返回JSON响应的更多相关文章

  1. springmvc通过ajax异步请求返回json格式数据

    jsp 首先创建index.jsp页面 <script type="text/javascript"> $(function () { $("#usernam ...

  2. 异步请求返回json对象

    后台mvc: var result = new { flag = ture, eMail = "949096562@qq.com"}; if (result.flag) { ret ...

  3. 【Spring学习笔记-MVC-5】利用spring MVC框架,实现ajax异步请求以及json数据的返回

    作者:ssslinppp      时间:2015年5月26日 15:32:51 1. 摘要 本文讲解如何利用spring MVC框架,实现ajax异步请求以及json数据的返回. Spring MV ...

  4. ajax异步请求返回对象

    使用ajax异步请求返回一个对象. java code: @RequestMapping({"getAstSingleWheelImg_bbs"+Constant.JSON}) @ ...

  5. 在使用Ajax请求返回json数据的时候IE浏览器弹出下载保存对话框的解决方法

    在使用Ajax请求返回json数据的时候IE浏览器弹出下载保存对话框的解决方法 最近在做一个小东西,使用kindeditor上传图片的时候,自己写了一个上传的方法,按照协议规则通过ajax返回json ...

  6. AJAX请求,返回json进行页面绑值

    AJAX请求,返回json进行页面绑值 后台 controller @RequestMapping(value = "backjson.do",method=RequestMeth ...

  7. 异步请求取得json数据

    一.异步请求 在之前我们请求数据的时候都是整个页面全部刷新了一次,也就是每次请求都会重新请求所有的资源.但是在很多时候不需要页面全部刷新,仅仅是需要页面的局部数据刷新即可,此时需要发送异步请求来实现这 ...

  8. IOS-网络(HTTP请求、同步请求、异步请求、JSON解析数据)

    // // ViewController.m // IOS_0129_HTTP请求 // // Created by ma c on 16/1/29. // Copyright © 2016年 博文科 ...

  9. Ajax异步请求返回文件流(eg:导出文件时,直接将导出数据用文件流的形式返回客户端供客户下载)

    在异步请求中要返回文件流,不能使用JQuery,因为$.ajax,$.post 不支持返回二进制文件流的类型,可以看到下图,dataType只支持xml,json,script,html这几种格式,没 ...

随机推荐

  1. 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。例如2+22+222+2222+22222。

    方法一: var num = ""; var nums = []; var a = Number(prompt());//所要拼接的数字 var b = Number(prompt ...

  2. Go 变量(var) & 常量(const)

    变量 声明变量格式: var var_name var_type 变量在声明时会自动初始化: 数字: 0 string: "" bool: false 引用类型: nil 结构体: ...

  3. Python:程序练习题(二)

    Python:程序练习题(二) 2.1温度转换程序. 代码如下: t=input("请输入带符号的温度值(如:32C):") if t[-1] in ["C", ...

  4. CentOS下yum方式安装FFmpeg

    FFmpeg一个完整的跨平台解决方案,用于记录,转换和流式传输音频和视频. 文档:https://www.ffmpeg.org/documentation.html FFmpeg安装 1.安装Nux ...

  5. C# params 可变参数使用注意

    今天在一个 .NET Core 项目中调用一个自己实现的使用 params 可变参数的方法时触发了 null 引用异常,原以为是方法中没有对参数进行 null 值检查引起的,于是加上 check nu ...

  6. 一站式解决Mac--socket.gaierror: [Errno 8] nodename nor servname provided, or not known

    socket.gaierror: [Errno 8] nodename nor servname provided, or not known 原因:hostname 没有写在/etc/hosts里 ...

  7. new 关键字 和 newInstance() 方法的 区别

    区别1: new是一个关键字,可以说是一个指令: newInstance()是一个方法,Class对象的一个方法. 区别2: new主要作用是在内存中生成一个实例,而这个类可以没有提前加载到内从中: ...

  8. Windows安装与配置—MongoDB

    1,下载安装 打开下载链接:http://dl.mongodb.org/dl/win32/x86_64,选择后缀是2008plus-ssl-3.6.15.zip的版本,32位和64位通用. 2,安装配 ...

  9. 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 6

    23.4  API的设计原则和规范 API是服务提供方和使用方之间对接的通道,前面我们设计的一些简单API的例子,基本上比较随意,没有使用任何规范.设想一下,每个平台都可能存在大量的API,如果API ...

  10. pytest框架优化——清理历史截图图片和allure报告文件

    痛点分析: 当我们每次执行完用例的时候,如果出现bug或者是测试脚本出了问题,一般会通过测试报告.异常截图.日志来定位分析,但是我们发现运行次数多了之后,异常截图和测试报告会不停地增多,对我们定位分析 ...