shiro 返回json字符串 + 自定义filter
2018-07-06 01:24:54来源:博客园 阅读 ()
前言:
在前后端分离的项目中, 在使用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. 结果:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用 2020-06-06
- Dubbo 2.7.7 发布,FastJson 升级了! 2020-05-25
- API接口如何设计,实现统一格式返回? 2020-05-18
- 如何用Spring Boot整合Shiro+JWT?这里教大家一最最简单的方 2020-05-13
- 解决json字符串转为对象时LocalDateTime异常问题 2020-05-08
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash