解决shiro自定义filter后,ajax登录无法登录,并且无法显示静态资源的问题

这个问题困扰了我一天,看了下面两个文章,豁然开朗:

https://www.cnblogs.com/gj1990/p/8057348.html

https://412887952-qq-com.iteye.com/blog/2392741

按照如下方法即可解决无法显示静态资源问题:

一、让springboot拦截器来接管静态资源,同时在shiroconfig中通过new方式注册过滤器

1、代码一

 1 import java.util.Arrays;
 2 
 3 import org.slf4j.Logger;
 4 import org.slf4j.LoggerFactory;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 7 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 8 
 9 /**
10  * SpringBoot管理器
11  */
12 @Configuration
13 public class WebMvcConfiguration implements WebMvcConfigurer {
14 
15     private final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class);
16 
17     @Override
18     public void addInterceptors(InterceptorRegistry registry) {
19         registry.addInterceptor(new LoginRequiredInterceptor()).excludePathPatterns(Arrays.asList("/css/**", "/js/**","/img/**","/fonts/**"));
20     }
21 }

2、代码二

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 登录拦截器
 *
 *
 */
public class LoginRequiredInterceptor extends HandlerInterceptorAdapter {

    private final Logger logger = LoggerFactory.getLogger(LoginRequiredInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.info(request.getRequestURI());
        return super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.info(request.getRequestURI());
        super.afterCompletion(request, response, handler, ex);
    }
}

三、shiro配置中使用new方式生成filter

filters.put("authc", new ExtendFormAuthenticationFilter());
filterChainDefinitionMap.put("/**", "user,authc");

四、自定义filter

import com.simon.common.util.R;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;

public class ExtendFormAuthenticationFilter extends FormAuthenticationFilter {

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

    /**
     * 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
     * onAccessDenied是否执行取决于isAccessAllowed的值,如果返回true则onAccessDenied不会执行;如果返回false,执行onAccessDenied
     * 如果onAccessDenied也返回false,则直接返回,不会进入请求的方法(只有isAccessAllowed和onAccessDenied的情况下)
     * */

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

        if(this.isLoginRequest(request, response)) {
            if(this.isLoginSubmission(request, response)) {
                if(log.isTraceEnabled()) {
                    log.trace("Login submission detected. Attempting to execute login.");
                }

                return this.executeLogin(request, response);
            } else {
                if(log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }

                return true;
            }
        } else {
            if(log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication. Forwarding to the Authentication url [" + this.getLoginUrl() + "]");
            }

            this.saveRequestAndRedirectToLogin(request, response);
            return false;
        }
    }

    /** * 当登录成功 * @param token * @param subject * @param request * @param response * @return * @throws Exception */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest
                .getHeader("X-Requested-With"))) {// 不是ajax请求
            issueSuccessRedirect(request, response);
        } else {
            httpServletResponse.setCharacterEncoding("UTF-8");
            PrintWriter out = httpServletResponse.getWriter();

            //out.println("{\"success\":true,\"message\":\"登入成功\"}");
            out.println(R.ok());
            out.flush();
            out.close();
        }
        return false;
    }

    /** * 当登录失败 * @param token * @param e * @param request * @param response * @return */
    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        if (!"XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request)
                .getHeader("X-Requested-With"))) {// 不是ajax请求
            setFailureAttribute(request, e);
            return true;
        }
        try {
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            String message = e.getClass().getSimpleName();
            if ("IncorrectCredentialsException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"密码错误\"}");
            } else if ("UnknownAccountException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"账号不存在\"}");
            } else if ("LockedAccountException".equals(message)) {
                out.println("{\"success\":false,\"message\":\"账号被锁定\"}");
            } else {
                out.println("{\"success\":false,\"message\":\"未知错误\"}");
            }
            out.flush();
            out.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return false;
    }
}

第二种方式就是“取消Filter自动注册,不会添加到FilterChain中“,方法如下:
一、定义过滤器,如上第四步
二、在shiroconfig中声明自定义
FormAuthenticationFilter
    @Bean
    public ExtendFormAuthenticationFilter getLoginAdviceFilter(){
        ExtendFormAuthenticationFilter filter=new ExtendFormAuthenticationFilter();
        filter.setRememberMeParam("username");
        filter.setPasswordParam("password");
        //对应前端的checkbox的name = rememberMe
        filter.setRememberMeParam("rememberMe");
        filter.setLoginUrl(loginUrl);
        return filter;
    }

三、取消注册

    @Bean
    public FilterRegistrationBean registrationBean(ExtendFormAuthenticationFilter customFormAuthenticationFilter){
        FilterRegistrationBean registration = new FilterRegistrationBean(customFormAuthenticationFilter);
        registration.setEnabled(false);//怎么取消  Filter自动注册,不会添加到FilterChain中.
        return registration;
    }

通过以上步骤就实现了解决shiro自定义filter后,ajax登录无法登录,并且无法显示静态资源的问题



 

posted @ 2019-01-31 16:12  疯狗强尼  阅读(407)  评论(0编辑  收藏  举报