JwtAuthenticationFilter.java

package com.mycim.webapp.secutiry.shiro.filter;

import com.fa.sesa.exception.ErrorCode;
import com.fa.sesa.i18n.I18nUtils;
import com.mycim.framework.utils.msg.JsonUtils;
import com.mycim.framework.utils.msg.model.Response;
import com.mycim.framework.utils.msg.model.ResponseHeader;
import com.mycim.webapp.secutiry.jwt.JwtUtils;
import com.mycim.webapp.secutiry.jwt.token.JwtToken;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author pinyan.song
 */
public class JwtAuthenticationFilter extends BasicHttpAuthenticationFilter {

    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        req.getSession();
        String authorization = JwtUtils.getToken(req);
        try {
            JwtToken jwtToken = new JwtToken(authorization);
            /*
             * 提交给Realm 登录,发生异常代表失败,反之代表成功, 成功情况下,续存Token(更换)
             */
            getSubject(request, response).login(jwtToken);
            JwtUtils.setTokenToCookie(httpServletResponse, JwtUtils.sign(jwtToken));
        } catch (Exception e) {
            // 如果发生异常, 清空token
            JwtUtils.setTokenToCookie(httpServletResponse, null);
            //直接返回false,交给 onAccessDenied 处理
            return false;
        }

        return true;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        return isLoginAttempt(request, response);
    }

    private boolean tokenIsNull(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest) request;
        return JwtUtils.getToken(req) != null;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //false by default or we wouldn't be in this method
        boolean loggedIn = false;
        if (!isLoginAttempt(request, response) && tokenIsNull(request)) {
            loggedIn = executeLogin(request, response);
        }
        if (!loggedIn) {
            sendChallenge(request, response);
        }
        if(loggedIn){
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            if(httpServletRequest.getRequestURI().endsWith("/changepasswordedit.do")){//只允许修改提交不重定向
                return true;
            }
            String authorization = JwtUtils.getToken(httpServletRequest);
            JwtToken jwtToken = new JwtToken(authorization);
            if(jwtToken.isNeedUpdatePwd()){
                //跳转修改密码页面
                ((HttpServletResponse)response).sendRedirect("login.do?action=main");
            }
        }
        return loggedIn;
    }

    @Override
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
        return pathsMatch(getLoginUrl(), request);
    }

    @Override
    protected boolean sendChallenge(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        //如果为Ajax
        if (req.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(req.getHeader("X-Requested-With"))) {
            httpServletResponse.setStatus(200);
            httpServletResponse.setContentType("application/json;charset=utf-8");
            httpServletResponse.setHeader("Cache-Control", "no-cache");
            try {
                Response res = new Response();
                ResponseHeader responseHeader = new ResponseHeader();
                responseHeader.setCode(ErrorCode.invalid.getErrCode());
                responseHeader.setSubCode("ShiroValidationFailed");
                responseHeader.setSubMessage(I18nUtils.getMessage("token.time_out", "Token Time Out"));
                res.setHead(responseHeader);

                httpServletResponse.getWriter().write(JsonUtils.toString(res));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            //正常的struts请求 返回login
            try {
                redirectToLogin(req, httpServletResponse);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

}