前言:

  在前后端分离的项目中, 在使用shiro的时候, 我们绝大部分时候, 并不想让浏览器跳转到那个页面去, 而是告诉前端, 你没有登录, 或者没有访问权限. 那这时候, 我们就需要返回json字符串给前端, 让前端解析后, 根据状态执行相应的操作.

实现:

由于我现在的系统, 权限并不复杂, 所以在这里, 我自定义了一个过滤器.

当然, 如果想要更加省事, 可以继承user(org.apache.shiro.web.filter.authc.UserFilter) 或者 authc(org.apache.shiro.web.filter.authc.FormAuthenticationFilter) 过滤器, 当然, 也可以是别的过滤器.

1. 自定义过滤器

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse; public class JsonAuthLoginFilter extends AccessControlFilter { @Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
Subject subject = SecurityUtils.getSubject(); if(null != subject){
if(subject.isRemembered()){
return Boolean.TRUE;
}
if(subject.isAuthenticated()){
return Boolean.TRUE;
}
} return Boolean.FALSE ;
} @Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
JsonResponse<Void> res = JsonResponse.noLogin("请先登录");
WebUtils.out((HttpServletResponse) response, res);
return Boolean.FALSE ;
}
}

这里的JsonResponse是返回实体.

import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; @ApiModel
public class JsonResponse<T> implements Serializable { private static final long serialVersionUID = -7817536542662556767L; @ApiModelProperty("请求成功/失败标志")
private boolean success; @ApiModelProperty("状态码, -1:没有登录, -2:没有权限, -3:系统报错, 0: 后台返回错误信息, 1: 成功访问")
private int code; @ApiModelProperty("访问提示信息")
private String msg; @ApiModelProperty("后台返回数据")
private T data; public JsonResponse() {
} public JsonResponse(boolean success) {
this();
this.success = success;
} public JsonResponse(boolean success, String msg) {
this(success);
this.msg = msg;
} public JsonResponse(boolean success, String msg, int code) {
this(success, msg);
this.code = code;
} public JsonResponse(boolean success, String msg, int code, T data) {
this(success, msg, code);
this.data = data;
} public boolean isSuccess() {
return success;
} public void setSuccess(boolean success) {
this.success = success;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public static JsonResponse<Void> SUCCESS = new JsonResponse<>(true); public static <T> JsonResponse<T> success(T data) {
return new JsonResponse<>(true, null, JsonResStateEnum.SUCCESS, data);
} public static <T> JsonResponse<T> success(T data, String msg) {
return new JsonResponse<>(true, msg, JsonResStateEnum.SUCCESS, data);
} public static <T> JsonResponse<T> error(String msg) {
return new JsonResponse<>(false, msg, JsonResStateEnum.USER_ERROR);
} public static <T> JsonResponse<T> error(String msg, T data) {
return new JsonResponse<>(false, msg, JsonResStateEnum.USER_ERROR, data);
} public static <T> JsonResponse<T> error(String msg, int code) {
return new JsonResponse<>(false, msg, code);
} public static <T> JsonResponse<T> noLogin(String msg) {
return new JsonResponse<>(false, msg, JsonResStateEnum.NO_LOGIN);
} public static <T> JsonResponse<T> noPermission(String msg) {
return new JsonResponse<>(false, msg, JsonResStateEnum.NO_PERMISSION);
}
}

JsonResStateEnum是自定义状态枚举

public interface JsonResStateEnum  {

    /**
* 没有登录时的状态
*/
public static final Integer NO_LOGIN = -1; /**
* 没有访问权限时的状态
*/
public static final Integer NO_PERMISSION = -2; /**
* 系统错误时的错误, 不可掌控错误
*/
public static final Integer SYSTEM_ERROR = -3; /**
* token验证错误
*/
public static final Integer TOKEN_ERROR = -4; /**
* 由用户自定义返回的错误, 受用户掌控
*/
public static final Integer USER_ERROR = 0; /**
* 正常状态
*/
public static final Integer SUCCESS = 1; }

WebUtils.out是自定义的方法, 意在返回json字符串

public static  void out(HttpServletResponse response, JsonResponse jsonObj){
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
out = response.getWriter();
out.write(JSON.toJSONString(jsonObj));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}

通过这个过滤器, 可以过滤没有登录的用户, 并将json字符串返回给前端.

但是, 如果我登录之后, 去访问没有权限的资源, 这样子就不能解决了. 需要一个全局错误处理.

2. 全局错误处理

import com.alibaba.fastjson.JSON;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.session.UnknownSessionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; public class MyMvcExceptionHandler implements HandlerExceptionResolver { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.error(ex.getMessage(), ex); if (ex instanceof UnauthenticatedException || ex instanceof AuthenticationException || ex instanceof UnknownSessionException) {
return outJson(request, response, JsonResponse.noLogin("请先登录"));
}
if (ex instanceof UnauthorizedException || ex instanceof AuthorizationException) {
return outJson(request, response, JsonResponse.noPermission("没有访问权限"));
}
return outJson(request, response, JsonResponse.error(ex.getMessage(), JsonResStateEnum.SYSTEM_ERROR));
} private ModelAndView outJson(HttpServletRequest request, HttpServletResponse response, JsonResponse res) {
ModelAndView mv = new ModelAndView();
/* 使用response返回 */
response.setStatus(HttpStatus.OK.value()); //设置状态码
response.setContentType(MediaType.APPLICATION_JSON_VALUE); //设置ContentType
response.setCharacterEncoding("UTF-8"); //避免乱码
response.setHeader("Cache-Control", "no-cache, must-revalidate");
try {
String json = JSON.toJSONString(res);
response.getWriter().write(json);
} catch (IOException e) {
logger.error("与客户端通讯异常:" + e.getMessage(), e);
} return mv;
}
}

3. 配置

在application.xml配置文件中

<bean id="exceptionHandler" class="common.myexception.MyMvcExceptionHandler"/>
<bean name="loginFilter" class="shiro.filter.JsonAuthLoginFilter" /> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="${shiro.loginUrl}"/>
<property name="filters">
<map>
<entry key="login" value-ref="loginFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<value>
/logout=logout
/user/retrievePwd = anon
/user/signOut = anon
/user/loginGet = anon
/swagger-ui.html = anon
/swagger-resources = anon
/swagger-resources/** = anon
/v2/api-docs = anon
/webjars/** = anon
/webjars/springfox-swagger-ui/** = anon
/user/login = anon
/user/register = anon
/** = login
</value>
</property>
</bean>

4. 结果:

shiro 返回json字符串 + 自定义filter的更多相关文章

  1. springMvc返回Json中自定义日期格式

    (一)输出json数据 springmvc中使用jackson-mapper-asl即可进行json输出,在配置上有几点: 1.使用mvc:annotation-driven 2.在依赖管理中添加ja ...

  2. @ResponseBody 返回json字符串的核心类是org.springframework.http.converter.json.MappingJacksonHttpMessageConverter,它使用了Jackson 这个开源的第三方类库。主要是以下两个jar包:jackson-core-asl-1.6.4.jar;jackson-mapper-asl-1.6.4.jar

    @ResponseBody 返回json字符串的核心类是org.springframework.http.converter.json.MappingJacksonHttpMessageConvert ...

  3. spring mvc返回json字符串的方式

    spring mvc返回json字符串的方式 方案一:使用@ResponseBody 注解返回响应体 直接将返回值序列化json            优点:不需要自己再处理 步骤一:在spring- ...

  4. springmvc返回json字符串中文乱码问题

    问题: 后台代码如下: @RequestMapping("menuTreeAjax") @ResponseBody /** * 根据parentMenuId获取菜单的树结构 * @ ...

  5. HttpClient 模拟发送Post和Get请求 并用fastjson对返回json字符串数据解析,和HttpClient一些参数方法的deprecated(弃用)的综合总结

    最近在做一个接口调用的时候用到Apache的httpclient时候,发现引入最新版本4.5,DefaultHttpClient等老版本常用的类已经过时了,不推荐使用了:去官网看了一下在4.3之后就抛 ...

  6. ajax请求返回json字符串/json对象 处理

    1. 返回json字符串如何处理 $.ajax({ url:xxx, success:function(date){ }, error:function(){ } }); 通过最原始的返回: Prin ...

  7. Jsoup请求http或https返回json字符串工具类

    Jsoup请求http或https返回json字符串工具类 所需要的jar包如下: jsoup-1.8.1.jar 依赖jar包如下: httpclient-4.5.4.jar; httpclient ...

  8. 160506、Spring mvc新手入门(11)-返回json 字符串的其他方式

    Spring MVC返回 json字符串的方式有很多种方法,这里介绍最简单,也是最常使用的两种方式 一.使用  PrintWriter printWriter  直接输出字符串到返回结果中    不需 ...

  9. SpringMVC返回Json,自定义Json中Date类型格式

    http://www.cnblogs.com/jsczljh/p/3654636.html —————————————————————————————————————————————————————— ...

随机推荐

  1. 今天我给你们推荐一本书《Linux就该这么学》!!!

    本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...

  2. es6剩余参数

    function show(a,b,...args){ console.log(a) console.log(b) console.log(args) } show(10,20,30,30,36)

  3. Python的list循环遍历中,删除数据的正确方法

    在遍历list,删除符合条件的数据时,总是报异常,代码如下: num_list = [1, 2, 3, 4, 5] print(num_list) for i in range(len(num_lis ...

  4. 取消Debian屏保及显示器休眠

    在产品展示场合,屏保及休眠会带来不好的体验,很多时候需要关闭掉. dpms显示器休眠设置: 开启:$ sudo xset dpms 1 1 2取消:$ sudo xset -dpms xset设置屏保 ...

  5. 使用tcpdump探测TCP/IP三次握手

    读计算机应该就同说过TCP/IP三次握手,但是都没有去验证过,今天心血来潮,去验证了一下,于是乎写下了这篇博客,可能写的可能有问题,还请多多指教 包括我学习,还有从很多资料来看资料,第三次握手,应该会 ...

  6. html文件上传保存-(.html and string translate into .html )

    //上传h5编辑器编辑的html内容 uploadHtml(newsId?: any) { const news = newsId !== undefined ? newsId : 'new'; le ...

  7. <笔记>TP5的save方法返回值

    用save方法来更新数据时,若更新前后数据没有改变则返回0,更新成功返回影响行数,更新失败返回false 若想要数据没改变时提示修改成功,则需要严格判断 if(结果!==false){提示成功}而不是 ...

  8. flask-钩子函数&g对象

    常用钩子函数 在Flask中钩子函数是使用特定的装饰器装饰的函数.钩子函数可以在正常执行的代码中,插入一段自己想要执行的代码.那么这种函数就叫做钩子函数.(hook) before_first_req ...

  9. VMware安装xp虚拟机

    VMware安装xp虚拟机 1.用到的软件: 2.安装VMware:  接受 选择自定义 要等上一小会. 输入密钥:百度一个就可以了. 安装成功: 禁用VMware网卡: 3.安装xp系统: 创建新的 ...

  10. 关于Selenium WebDriver的geckodriver

    下载Selenium的最新版本地址:http://selenium-release.storage.googleapis.com/index.html 友情提示:如果一直下载不了,可能是浏览器与下载工 ...