shiro+springboot:MyFormAuthenticationFilter(自定义认证拦截)

 在自定义认证拦截中,onAccessDenied 为入口,在onAccessDenied中调用自定义的认证方式(也可直接使用

FormAuthenticationFilter的父类的认证方式,但是使用默认的无法自定义认证成功/失败后的操作)

executeLogin(ServletRequest request, ServletResponse response) 认证方式

onLoginSuccess认证成功后操作   onLoginFailure认证失败后操作     供认证使用

/**
 * 所有请求都会经过的方法。
 */
@Override
protected boolean onAccessDenied(ServletRequest request,
                                 ServletResponse response) throws Exception {
//会在这里调用认证
}

/*
 *  主要是针对登入成功的处理方法。对于请求头是AJAX的之间返回JSON字符串。
 */
@Override
protected boolean onLoginSuccess(AuthenticationToken token,
                                 Subject subject, ServletRequest request, ServletResponse response)
        throws Exception {
//在这里写登入成功的处理,如需要在登陆成功后返回的数据
}
/**
 * 主要是处理登入失败的方法
 */
@Override
protected boolean onLoginFailure(AuthenticationToken token,
                                 AuthenticationException e, ServletRequest request,
                                 ServletResponse response) {
    if (!isAjaxRequest((HttpServletRequest) request)) {
//在这里写登入失败的处理,如需要在登陆失败后返回的数据
}
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSONObject;
import com.sinochem.erp.common.entity.MaterialCategory;
import com.sinochem.erp.common.entity.Org;
import com.sinochem.erp.common.entity.Permissions;
import com.sinochem.erp.common.entity.User;
import com.sinochem.erp.security.exception.IncorrectCaptchaException;
import com.sinochem.erp.service.OrgService;
import com.sinochem.erp.service.UserService;
import com.sinochem.erp.service.impmain.MaterialCategoryService;
import com.sinochem.erp.service.impmain.PermissionsServcie;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by topcat on 2017/4/10.
 */
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    public static final String DEFAULT_CAPTCHA_PARAM = "captcha";

    private String captchaParam = DEFAULT_CAPTCHA_PARAM;
    private UserService userService;
    private MaterialCategoryService materialCategoryMapper;
    private PermissionsServcie permissionsServcie;
    private OrgService orgService;

    private static final Logger log = LoggerFactory.getLogger(CaptchaFormAuthenticationFilter.class);

    public CaptchaFormAuthenticationFilter(UserService userService, MaterialCategoryService materialCategoryMapper, PermissionsServcie permissionsServcie,OrgService orgService) {
        this.userService = userService;
        this.materialCategoryMapper = materialCategoryMapper;
        this.permissionsServcie = permissionsServcie;
        this.orgService=orgService;
    }

    public String getCaptchaParam() {
        return captchaParam;
    }

    public void setCaptchaParam(String captchaParam) {
        this.captchaParam = captchaParam;
    }

    protected String getCaptcha(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }

    // 创建 Token
    protected CaptchaUsernamePasswordToken createToken(
            ServletRequest request, ServletResponse response) {
        //获取手机类型
        HttpServletRequest httpServletRequest =(HttpServletRequest) request;
        String platforms = httpServletRequest.getHeader("platforms");
        String username = getUsername(request);
        String password = getPassword(request);
        String captcha = getCaptcha(request);
       // boolean rememberMe = isRememberMe(request);
        boolean rememberMe = true;
        String host = getHost(request);
        return new CaptchaUsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha,platforms);
    }

    // 验证码校验
    protected void doCaptchaValidate(HttpServletRequest request, CaptchaUsernamePasswordToken token) {

        String captcha = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);

        if (captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha())) {
            throw new IncorrectCaptchaException("验证码错误!");
        }
    }

    // 认证
    protected boolean executeLogin(ServletRequest request,
                                   ServletResponse response) throws Exception {
        CaptchaUsernamePasswordToken token = createToken(request, response);

        try {
            //暂不需要做验证码校验
            //doCaptchaValidate((HttpServletRequest) request, token);

            Subject subject = getSubject(request, response);
            subject.login(token);
            //认证成功
            return onLoginSuccess(token, subject, request, response);
        } catch (AuthenticationException e) {
            //认证失败
            return onLoginFailure(token, e, request, response);
        }
    }

    public class CaptchaUsernamePasswordToken extends UsernamePasswordToken {

        private String captcha;
        private String platforms;

        public String getPlatforms() {
            return platforms;
        }

        public void setPlatforms(String platforms) {
            this.platforms = platforms;
        }

        public String getCaptcha() {
            return captcha;
        }

        public void setCaptcha(String captcha) {
            this.captcha = captcha;
        }

        public CaptchaUsernamePasswordToken(String username, char[] password,
                                            boolean rememberMe, String host, String captcha,String platforms) {
            super(username, password, rememberMe, host);
            this.captcha = captcha;
            this.platforms=platforms;
        }
    }

    /*
     *  主要是针对登入成功的处理方法。对于请求头是AJAX的之间返回JSON字符串。
     *  可在这定义一些登陆成功时返回的数据
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token,
                                     Subject subject, ServletRequest request, ServletResponse response)
            throws Exception {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        User user = (User) subject.getPrincipal();
        recordLastLoginTime(user);
        //初始化数据
        initSession();
        //获取权限
        initPermissions(user);
        if (!isAjaxRequest((HttpServletRequest) request)) {// 不是ajax请求
            issueSuccessRedirect(request, response);
        } else {
            httpServletResponse.setCharacterEncoding("UTF-8");
            PrintWriter out = httpServletResponse.getWriter();
            JSONObject j = new JSONObject();
            initJson(subject, user, j);
            out.println(j.toJSONString());
            out.flush();
            out.close();
        }
        return false;
    }

    private void initJson(Subject subject, User user, JSONObject j) {
        j.put("status", "200");
        j.put("message", "登入成功");
        j.put("success", true);
        User newUser = new User();
        try {
            BeanUtils.copyProperties(newUser, user);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        newUser.setPwd(null);
        newUser.setSalt(null);
        Session session = subject.getSession();
        List list = (List) session.getAttribute("permissions");
        Map map = new HashMap();
        map.put("User", newUser);
        map.put("Permissions", list);
        Org parentOrg=orgService.getParent(user.getOrgCode());
        map.put("parent",parentOrg);
        j.put("data", map);
    }

    private void initSession() {
        Session session = SecurityUtils.getSubject().getSession();
        Map map = new HashMap();
        //获取UDC 对应的Unit汉字名称
        initUDC(session, map);
    }

    private void initUDC(Session session, Map map) {
        MaterialCategory materialCategory = new MaterialCategory();
        materialCategory.setCode("00");
        materialCategory.setUserCode("UM");
        List materialCategories = materialCategoryMapper.getMaterialCategorys(materialCategory);
        Map udc = new HashMap<>();
        materialCategories.forEach(materialCategorie -> {
            if (StringUtils.isNotBlank(materialCategorie.getCustomCode())) {
                udc.put(materialCategorie.getCustomCode(), materialCategorie.getRemark());
            }
        });
        map.put("UDC", udc);
        session.setAttribute("UDC", map);
    }

    private void initPermissions(User user) {
        Session session = SecurityUtils.getSubject().getSession();
        List permissionsList = permissionsServcie.getPermissionsByuser(user.getId());
       /* Map permissionMap = new HashMap<>();
       permissionsList.forEach(permission -> {
            if (StringUtils.isNotBlank(permission.getName())) {
                permissionMap.put(permission.getName(),permission.getCode());
            }
        });*/
        // map.put("permissions", permissionMap);
        session.setAttribute("permissions", permissionsList);
    }

    private void recordLastLoginTime(User user) {
//        user.setLastLoginTime(new Date());
        userService.updateById(user);
    }

    /**
     * 主要是处理登入失败的方法
     */
    @Override
    protected boolean onLoginFailure(AuthenticationToken token,
                                     AuthenticationException e, ServletRequest request,
                                     ServletResponse response) {
        if (!isAjaxRequest((HttpServletRequest) request)) {// 不是ajax请求
            setFailureAttribute(request, e);
            return true;
        }
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            PrintWriter out = response.getWriter();
            String message = e.getClass().getSimpleName();
            String res = "";
            if (e.getCause() != null) {
                res = e.getCause().getClass().getSimpleName();
            }
            if ("IncorrectCredentialsException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"密码错误\",\"status\":500}");
            } else if ("UnknownAccountException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"账号不存在\",\"status\":500}");
            } else if ("MoreUsersException".equals(message) || res.equals("MoreUsersException")) {
                out.println("{\"success\":false,\"message\":\"多个用户名,请联系重置\",\"status\":500}");
            } else if ("IncorrectCaptchaException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"验证码不正确\",\"status\":500}");
            } else {
                out.println("{\"success\":false,\"message\":\"未知错误\",\"status\":500}");
            }
            out.flush();
            out.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return false;
    }

    /**
     * 所有请求都会经过的方法。
     */
    @Override
    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((HttpServletRequest) request)) {// 不是ajax请求
                saveRequestAndRedirectToLogin(request, response);
            } else {
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                HttpServletResponse r = (HttpServletResponse) response;
                r.setStatus(HttpStatus.OK.value());
                response.setCharacterEncoding("UTF-8");
                PrintWriter out = response.getWriter();
                out.println("{\"success\":false,\"message\":\"login\",\"status\":401}");
                out.flush();
                out.close();
            }
            return false;
        }
    }

    private boolean isAjaxRequest(HttpServletRequest request) {
        return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
    }


}

 

你可能感兴趣的:(shiro,springboot)