SpringBoot中Shiro處理ajax請求(重寫UserFilter)


首先道歉 沒經過充分的測試就發文了 后來在review的時候發現我在map中同一個key塞了倆對象

這樣只有最后添加的有效 在看了shiro相關文檔之后找到了有效的解決方法

文章末尾我會補上Shiro自帶的攔截器相關內容

 

寫一個Shiro的過濾器 繼承org.apache.shiro.web.filter.authc.UserFilter

import com.zzyk.common.model.vo.Message;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.UserFilter;

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

public class GenericFilter extends UserFilter {

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        resp.setCharacterEncoding("UTF-8");
        resp.setHeader("ContentType", "text/html;charset=UTF-8");
        String requestedWith = req.getHeader("X-Requested-With");

        if ("XMLHttpRequest".equals(requestedWith)) {
            Message message = new Message();
            message.setCode(403);
            message.setMessage("請登錄后操作");
            resp.getWriter().write(JSON.toJSONString(message));
        } else {
            this.saveRequestAndRedirectToLogin(request, response);
        }
        return false;
    }
}

 

Shiro的配置類里面的配置我就全部放出來了 就看一下與這次配置相關的

@Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        // 設置登錄界面URL
        factoryBean.setLoginUrl(loginUrl);
        // 設置未經認證頁面的URL
        factoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // 設置登錄成功后跳轉的URL
        factoryBean.setSuccessUrl(indexUrl);

        HashMap<String, Filter> filter = new HashMap<>();
        filter.put("authc", new GenericFilter());
        filter.put("logout", new LogoutFilter());
        factoryBean.setFilters(filter);

        // 需要認證的加到authc里面
        // 不需要認證的加到anon里面
        HashMap<String, String> filterChain = new HashMap<>();
        filterChain.put("/customize/**", "anon");
        filterChain.put("/plugins/**", "anon");
        filterChain.put("/layuiadmin/**", "anon");
        filterChain.put("/favicon.ico", "anon");
        filterChain.put("/sys/login", "anon");
        filterChain.put("/sys/status", "anon");
        filterChain.put("/sys/captcha", "anon");
        filterChain.put("/device/notice", "anon");
        filterChain.put("/druid/**", "anon");
        filterChain.put("/sys/logout", "logout");

        filterChain.put("/**", "authc");
        factoryBean.setFilterChainDefinitionMap(filterChain);

        return factoryBean;
    }

另外不知道為啥我用jquery的ajax發出的請求都沒有X-Requested-With請求頭(郁悶...)

我就包裝了一下jquery的ajax 手動把這個請求頭加上 順便處理了一下跨域問題

function getJson(url, params, method, success) {
    $.ajax({
        url: host + url,
        data: params,
        method: method,
        async: true,
        dataType: "json",
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        beforeSend: function (xhr) {
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
        },
        success: function (data) {
            if (data['code'] == 403) {
                alert(data['message']);
                top.location.href = 'login.html'
            } else {
                if (success) {
                    success(data);
                }
            }
        }, error: function () {
            alert('服務器錯誤,請聯系管理員');
        }
    });
}

這樣ajax和網頁請求都能正常處理了


注意一個過濾器名只能配一個過濾器 一個資源可以配多個過濾器名 方法為逗號分割 例如

// 定義過濾器
HashMap<String, Filter> filter = new HashMap<>(); filter.put("authc", new GenericFilter()); filter.put("default", new FormAuthenticationFilter()); filter.put("logout", new LogoutFilter()); factoryBean.setFilters(filter);
// 定義過濾鏈 HashMap
<String, String> filterChain = new HashMap<>(); filterChain.put("/**", "authc,default"); factoryBean.setFilterChainDefinitionMap(filterChain);

 

DefaultFilterChainManager 會默認添加 org.apache.shiro.web.filter.mgt.DefaultFilter 中聲明的攔截器

public enum DefaultFilter { 
    anon(AnonymousFilter.class), 
    authc(FormAuthenticationFilter.class), 
    authcBasic(BasicHttpAuthenticationFilter.class), 
    logout(LogoutFilter.class), 
    noSessionCreation(NoSessionCreationFilter.class), 
    perms(PermissionsAuthorizationFilter.class), 
    port(PortFilter.class), 
    rest(HttpMethodPermissionFilter.class), 
    roles(RolesAuthorizationFilter.class), 
    ssl(SslFilter.class), 
    user(UserFilter.class); 
} 

攔截器說明

默認攔截器名 攔截器類 說明 主要參數
身份驗證相關 org.apache.shiro.web.filter.authc
authc FormAuthenticationFilter

基於表單的攔截器

usernameParam: 用戶名(username)

passwordParam: 密碼(password)

rememberMeParam: 記住密碼(remember)

loginUrl: 登錄頁面("/login.jsp")

successUrl: 登錄成功后重定向的頁面

failureKeyAttribute: 登錄失敗后

    錯誤信息存儲(shiroLoginFailure)

authcBasic BasicHttpAuthenticationFilter

Basic HTTP身份驗證攔截器

就是瀏覽器彈出登錄窗口的那種

applicationName: 登錄框顯示的信息(application)
logout LogoutFilter 退出登錄攔截器 redirectUrl: 退出登錄重定向的頁面("/")
user UserFilter

用戶攔截器

用於驗證用戶是否通過身份驗證

 
anon AnonymousFilter 匿名攔截器 無需認證即可訪問  
授權相關 org.apache.shiro.web.filter.authz
roles RolesAuthorizationFilter 角色授權攔截器

loginUrl: 登錄頁面("/login.jsp")

unauthorizedUrl: 未授權跳轉的頁面

perms PermissionsAuthorizationFilter 權限授權攔截器  

未完全實現

1.3.2版本不可用

HostFilter

主機地址攔截器

我調用直接拋異常說暫未實現

authorizedIps: 已授權的ip地址

deniedIPS: 已拒絕的ip地址

port PortFilter 端口攔截器

port: 允許通過的端口

如果是非指定端口訪問 則重定向到該端口

rest HttpMethodPermissionFilter

rest風格攔截器 根據請求方法構建權限字符串

GET=read

POST=create

PUT=update

DELETE=delete

HEAD=read

TEACE=read

OPTIONS=read

MKCOL=create

ssl SslFilter SSL攔截器

無參數 只允許https請求通過

如果是非http請求會重定向到443端口

其他
org.apache.shiro.web.filter.session
noSessionCreation NoSessionCreationFilter

不創建會話(Session)攔截器

調用subject.getSession(false)沒問題

調用subject.getSession(true)會拋異常

DisabledSessionException

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

節選自《跟我學SHiro》並重新排版,修改了部分內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM