package com.gkhy.assess.framework.shiro.filter; import com.alibaba.fastjson.JSONObject; import com.gkhy.assess.common.api.CommonResult; import com.gkhy.assess.common.api.ResultCode; import com.gkhy.assess.common.utils.JwtTokenUtil; import com.gkhy.assess.common.domain.JwtToken; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; import org.apache.shiro.web.util.WebUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; @Slf4j public class JwtFilter extends BasicHttpAuthenticationFilter { /** * 默认开启跨域设置(使用单体) * 微服务情况下,此属性设置为false */ private boolean allowOrigin = true; public JwtFilter(){} public JwtFilter(boolean allowOrigin){ this.allowOrigin=allowOrigin; } /** * 前置拦截处理 * @param request * @param response * @return * @throws Exception */ @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { //servlet请求与响应的转换 HttpServletRequest httpServletRequest = WebUtils.toHttp(request); HttpServletResponse httpServletResponse = WebUtils.toHttp(response); if(allowOrigin){ this.fillCorsHeader(WebUtils.toHttp(request), WebUtils.toHttp(response)); } //跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态 if(httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())){ httpServletResponse.setStatus(HttpStatus.OK.value()); return false; } return super.preHandle(request, response); } /** * 过滤器拦截请求的入口方法,所有请求都会进入该方法 * 返回true则允许访问 * @param request * @param response * @param mappedValue * @return */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { try{ //检测header里的JWT Token内容是否正确,尝试使用token进行登录 this.executeLogin(request,response); return true; } catch (Exception e){ //未找到token log.error(e.getMessage()); JwtTokenUtil.responseError(response,e.getMessage()); } return false; } /** * 身份验证,检查JWT token是否合法 * @param request * @param response * @return * @throws Exception */ @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String jwtToken = httpServletRequest.getHeader(JwtTokenUtil.USER_LOGIN_TOKEN); JwtToken token=new JwtToken(jwtToken); Subject subject = getSubject(request,response); subject.login(token); return true; } /** * isAccessAllowed()方法返回false,会进入该方法,表示拒绝访问 * @param request * @param response * @return * @throws Exception */ @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { HttpServletResponse httpServletResponse = WebUtils.toHttp(response); httpServletResponse.setCharacterEncoding("UTF-8"); httpServletResponse.setContentType("application/json;charset=UTF-8"); httpServletResponse.setStatus(HttpStatus.OK.value()); PrintWriter writer = httpServletResponse.getWriter(); writer.write(JSONObject.toJSONString(CommonResult.failed(ResultCode.UNAUTHORIZED))); return false; } //跨域请求的解决方案之一 protected void fillCorsHeader(HttpServletRequest request, HttpServletResponse response){ response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeader(HttpHeaders.ORIGIN)); // 允许客户端请求方法 response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,OPTIONS,HEAD,PUT,DELETE"); // 允许客户端提交的Header String requestHeaders = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS); if (StringUtils.isNotEmpty(requestHeaders)) { response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders); } // 允许客户端携带凭证信息(是否允许发送Cookie) response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); } }