日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第8章 拦截器机制

發布時間:2025/4/14 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第8章 拦截器机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

8.1 攔截器介紹

Shiro使用了與Servlet一樣的Filter接口進行擴展,所以如果對Filter不熟悉可以參考《Servlet3.1規范》http://www.iteye.com/blogs/subjects/Servlet-3-1了解Filter的工作原理,首先下圖是Shiro攔截器的基礎類圖:

1.NameableFilter

NameableFilter給Filter起個名字,如果沒有設置默認就是FilterName,還記得之前的如authc嗎?當我們組裝攔截器鏈時會根據這個名字找到相應的攔截器實例.

2.OncePerRequestFilter

OncePerRequestFilter用于防止多次執行Filter的,也就是說一次請求只會走一次攔截器鏈,另外提供enabled屬性,表示是否開啟該攔截器實例,默認enabled=true表示開啟,如果不想讓某個攔截器工作,可以設置為false即可。

3.ShiroFilter

ShiroFilter是整個Shiro的入口點,用于攔截需要安全控制的請求進行處理,這個之前已經用過了。

4.AdviceFilter(建議)

AdviceFilter提供了AOP風格的支持,類似于SpringMVC中的Interceptor:

boolean preHandle(ServletRequest request, ServletResponse response) throws Exception?

void postHandle(ServletRequest request, ServletResponse response) throws Exception?

void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception;??

preHandler類似于AOP中的前置增強,在攔截器鏈執行之前執行,如果返回true則繼續攔截器鏈,否則中斷后續的攔截器鏈的執行直接返回,進行預處理(如基于表單的身份驗證、授權)。

postHandle類似于AOP中的后置返回增強,在攔截器鏈執行完成后執行,進行后處理(如記錄執行時間之類的)。

afterCompletion類似于AOP中的后置最終增強,即不管有沒有異常都會執行,可以進行清理資源(如接觸Subject與線程的綁定之類的)。

5.PathMatchingFilter(路徑配套)

PathMatchingFilter提供了基于Ant風格的請求路徑匹配功能及攔截器參數解析的功能,如“roles[admin,user]”自動根據“,”分割解析到一個路徑參數配置并綁定到相應的路徑:

boolean pathsMatch(String path, ServletRequest request)?

boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception?

pathsMatch:該方法用于path與請求路徑進行匹配的方法,如果匹配返回true。

onPreHandle在preHandle中,當pathsMatch匹配一個路徑后,會調用opPreHandler方法并將路徑綁定參數配置傳給mappedValue,然后可以在這個方法中進行一些驗證(如角色授權),如果驗證失敗可以返回false中斷流程,默認返回true,也就是說子類可以只實現onPreHandle即可,無須實現preHandle,如果沒有path與請求路徑匹配,默認是通過的(即preHandle返回true)。

6.AccessControlFilter

AccessControlFilter提供了訪問控制的基礎功能,比如是否允許訪問/當訪問拒絕時如何處理等:

abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;?

boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;

abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;??

abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;

boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;

abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;

isAccessAllowed表示是否允許訪問,mappedValue就是[urls]配置中攔截器參數部分,如果允許訪問返回true,否則false;

onAccessDenied表示當訪問拒絕時是否已經處理了,如果返回true表示需要繼續處理,如果返回false表示該攔截器實例已經處理了,將直接返回即可。

onPreHandle會自動調用這兩個方法決定是否繼續處理:

boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {?

??? return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);?

}??

boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);

}

另外AccessControlFilter還提供了如下方法用于處理如登錄成功后/重定向到上一個請求:

void setLoginUrl(String loginUrl) //身份驗證時使用,默認/login.jsp?

String getLoginUrl()?

Subject getSubject(ServletRequest request, ServletResponse response) //獲取Subject實例

boolean isLoginRequest(ServletRequest request, ServletResponse response)//當前請求是否是登錄請求

void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException //將當前請求保存起來并重定向到登錄頁面

void saveRequest(ServletRequest request) //將請求保存起來,如登錄成功后再重定向回該請求

void redirectToLogin(ServletRequest request, ServletResponse response) //重定向到登錄頁面

void setLoginUrl(String loginUrl) //身份驗證時使用,默認/login.jsp

String getLoginUrl()

Subject getSubject(ServletRequest request, ServletResponse response) //獲取Subject實例

boolean isLoginRequest(ServletRequest request, ServletResponse response)//當前請求是否是登錄請求

void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException //將當前請求保存起來并重定向到登錄頁面

void saveRequest(ServletRequest request) //將請求保存起來,如登錄成功后再重定向回該請求

void redirectToLogin(ServletRequest request, ServletResponse response) //重定向到登錄頁面

比如基于表單的身份驗證就需要使用這些功能。

到此基本的攔截器就完事了,如果我們想進行訪問訪問的控制就可以繼承AccessControlFilter;如果我們要添加一些通用數據我們可以直接繼承PathMatchingFilter。

8.2 攔截器鏈

Shiro對Servlet容器的FilterChain進行了代理,即ShiroFilter在繼續Servlet容器的Filter鏈的執行之前,通過ProxiedFilterChain對Servlet容器的FilterChain進行了代理,即先走Shiro自己的Filter體系,然后才會委托給Servlet容器的FilterChain進行Servlet容器級別的Filter鏈執行。Shiro的ProxiedFilterChain執行流程:

1.先執行Shiro自己的Filter鏈;

2.再執行Servlet容器的Filter鏈(即原始的Filter)。

而ProxiedFilterChain是通過FilterChainResolver根據配置文件中[urls]部分是否與請求的URL是否匹配解析得到的。

FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);?

即傳入原始的chain得到一個代理的chain。Shiro內部提供了一個路徑匹配的FilterChainResolver實現:PathMatchingFilterChainResolver,其根據[urls]中配置的url模式(默認Ant風格)=攔截器鏈和請求的url是否匹配來解析得到配置的攔截器鏈的,而PathMatchingFilterChainResolver內部通過FilterChainManager維護著攔截器鏈,比如DefaultFilterChainManager實現維護著url模式與攔截器鏈的關系,因此我們可以通過FilterChainManager進行動態動態增加url模式與攔截器鏈的關系。

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);?

}??

下一節會介紹這些攔截器的作用。

如果要注冊自定義攔截器,IniSecurityManagerFactory/WebIniSecurityManagerFactory在啟動時會自動掃描ini配置文件中的[filters]/[main]部分并注冊這些攔截器到DefaultFilterChainManager,且創建相應的url模式與其攔截器關系鏈,如果使用Spring后續章節會介紹如果注冊自定義攔截器。 如果想自定義FilterChainResolver,可以通過實現WebEnvironment接口完成:

public class MyIniWebEnvironment extends IniWebEnvironment {?

@Override

??? protected FilterChainResolver createFilterChainResolver() {?

??????? //在此處擴展自己的FilterChainResolver?

??????? return super.createFilterChainResolver();?

??? }?

}??

public class MyIniWebEnvironment extends IniWebEnvironment {

@Override

protected FilterChainResolver createFilterChainResolver() {

//在此處擴展自己的FilterChainResolver

return super.createFilterChainResolver();

}

}

FilterChain之間的關系。如果想動態實現url-攔截器的注冊,就可以通過實現此處的FilterChainResolver來完成,比如:

//1、創建FilterChainResolver?

PathMatchingFilterChainResolver filterChainResolver =?

??????? new PathMatchingFilterChainResolver();?

//2、創建FilterChainManager?

DefaultFilterChainManager filterChainManager = new DefaultFilterChainManager();?

//3、注冊Filter?

for(DefaultFilter filter : DefaultFilter.values()) {?

??? filterChainManager.addFilter(?

??????? filter.name(), (Filter) ClassUtils.newInstance(filter.getFilterClass()));?

}?

//4、注冊URL-Filter的映射關系

filterChainManager.addToChain("/login.jsp", "authc");?

filterChainManager.addToChain("/unauthorized.jsp", "anon");?

filterChainManager.addToChain("/**", "authc");?

filterChainManager.addToChain("/**", "roles", "admin");???

//5、設置Filter的屬性

FormAuthenticationFilter authcFilter =?

???????? (FormAuthenticationFilter)filterChainManager.getFilter("authc");?

authcFilter.setLoginUrl("/login.jsp");?

RolesAuthorizationFilter rolesFilter =?

????????? (RolesAuthorizationFilter)filterChainManager.getFilter("roles");?

rolesFilter.setUnauthorizedUrl("/unauthorized.jsp");???

filterChainResolver.setFilterChainManager(filterChainManager);?

return filterChainResolver;??

//1、創建FilterChainResolver

PathMatchingFilterChainResolver filterChainResolver =

new PathMatchingFilterChainResolver();

//2、創建FilterChainManager

DefaultFilterChainManager filterChainManager = new DefaultFilterChainManager();

//3、注冊Filter

for(DefaultFilter filter : DefaultFilter.values()) {

filterChainManager.addFilter(

filter.name(), (Filter) ClassUtils.newInstance(filter.getFilterClass()));

}

//4、注冊URL-Filter的映射關系

filterChainManager.addToChain("/login.jsp", "authc");

filterChainManager.addToChain("/unauthorized.jsp", "anon");

filterChainManager.addToChain("/**", "authc");

filterChainManager.addToChain("/**", "roles", "admin");

//5、設置Filter的屬性

FormAuthenticationFilter authcFilter =

(FormAuthenticationFilter)filterChainManager.getFilter("authc");

authcFilter.setLoginUrl("/login.jsp");

RolesAuthorizationFilter rolesFilter =

(RolesAuthorizationFilter)filterChainManager.getFilter("roles");

rolesFilter.setUnauthorizedUrl("/unauthorized.jsp");

filterChainResolver.setFilterChainManager(filterChainManager);

return filterChainResolver;

此處自己去實現注冊filter,及url模式與filter之間的映射關系。可以通過定制FilterChainResolver或FilterChainManager來完成諸如動態URL匹配的實現。

然后再web.xml中進行如下配置Environment:

<context-param>?

<param-name>shiroEnvironmentClass</param-name> <param-value>com.github.zhangkaitao.shiro.chapter8.web.env.MyIniWebEnvironment</param-value>?

</context-param>?? <context-param>

<param-name>shiroEnvironmentClass</param-name> <param-value>com.github.zhangkaitao.shiro.chapter8.web.env.MyIniWebEnvironment</param-value>

</context-param>

8.3 自定義攔截器

通過自定義自己的攔截器可以擴展一些功能,諸如動態url-角色/權限訪問控制的實現、根據Subject身份信息獲取用戶信息綁定到Request(即設置通用數據)、驗證碼驗證、在線用戶信息的保存等等,因為其本質就是一個Filter;所以Filter能做的它就能做。 對于Filter的介紹請參考《Servlet規范》中的Filter部分:

http://www.iteye.com/blogs/subjects/Servlet-3-1。

1.擴展OncePerRequestFilter

OncePerRequestFilter保證一次請求只調用一次doFilterInternal,即如內部的forward不會再多執行一次doFilterInternal:

public class MyOncePerRequestFilter extends OncePerRequestFilter {?

@Override

??? protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {?

??????? System.out.println("=========once per request filter");?

??????? chain.doFilter(request, response);?

??? }?

}

public class MyOncePerRequestFilter extends OncePerRequestFilter {

@Override

protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

System.out.println("=========once per request filter");

chain.doFilter(request, response);

}

}

然后再shiro.ini配置文件中:

[main]?

myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter?

#[filters]?

#myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter?

[urls]?

/**=myFilter1?

[main]

myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter

#[filters]

#myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter

[urls]

/**=myFilter1

Filter可以在[main]或[filters]部分注冊,然后在[urls]部分配置url與filter的映射關系即可。

2.擴展AdviceFilter

AdviceFilter提供了AOP的功能,其實現和SpringMVC中的Interceptor思想一樣:具體可參考我的SpringMVC教程中的處理器攔截器部分:http://www.iteye.com/blogs/subjects/kaitao-springmvc

public class MyAdviceFilter extends AdviceFilter {?

@Override

??? protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {?

??????? System.out.println("====預處理/前置處理");?

??????? return true;//返回false將中斷后續攔截器鏈的執行

??? }?

@Override

??? protected void postHandle(ServletRequest request, ServletResponse response) throws Exception {?

??????? System.out.println("====后處理/后置返回處理");?

??? }?

@Override

??? public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception {?

??????? System.out.println("====完成處理/后置最終處理");?

??? }?

}??

public class MyAdviceFilter extends AdviceFilter {

@Override

protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {

System.out.println("====預處理/前置處理");

return true;//返回false將中斷后續攔截器鏈的執行

}

@Override

protected void postHandle(ServletRequest request, ServletResponse response) throws Exception {

System.out.println("====后處理/后置返回處理");

}

@Override

public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception {

System.out.println("====完成處理/后置最終處理");

}

}

preHandle進行請求的預處理,然后根據返回值決定是否繼續處理(true:繼續過濾器鏈);可以通過它實現權限控制;

postHandle執行完攔截器鏈之后正常返回后執行;

afterCompletion不管最后有沒有異常,afterCompletion都會執行,完成如清理資源功能。

然后在shiro.ini中進行如下配置:

[filters]?

myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter?

myFilter2=com.github.zhangkaitao.shiro.chapter8.web.filter.MyAdviceFilter?

[urls]?

/**=myFilter1,myFilter2??

[filters]

myFilter1=com.github.zhangkaitao.shiro.chapter8.web.filter.MyOncePerRequestFilter

myFilter2=com.github.zhangkaitao.shiro.chapter8.web.filter.MyAdviceFilter

[urls]

/**=myFilter1,myFilter2

該過濾器的具體使用可參考我的SpringMVC教程中的處理器攔截器部分。

3.PathMatchingFilter

PathMatchingFilter繼承了AdviceFilter,提供了url模式過濾的功能,如果需要對指定的請求進行處理,可以擴展PathMatchingFilter:

public class MyPathMatchingFilter extends PathMatchingFilter {?

@Override

??? protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {?

?????? System.out.println("url matches,config is " + Arrays.toString((String[])mappedValue));?

?????? return true;?

??? }?

}??

preHandle:會進行url模式與請求url進行匹配,如果匹配會調用onPreHandle;如果沒有配置url模式/沒有url模式匹配,默認直接返回true;

onPreHandle:如果url模式與請求url匹配,那么會執行onPreHandle,并把該攔截器配置的參數傳入。默認什么不處理直接返回true。

然后在shiro.ini中進行如下配置:

[filters]?

myFilter3=com.github.zhangkaitao.shiro.chapter8.web.filter.MyPathMatchingFilter?

[urls]?

/**= myFilter3[config]??

[filters]

myFilter3=com.github.zhangkaitao.shiro.chapter8.web.filter.MyPathMatchingFilter

[urls]

/**= myFilter3[config]

/**就是注冊給PathMatchingFilter的url模式,config就是攔截器的配置參數,多個之間逗號分隔,onPreHandle使用mappedValue接收參數值。

4.擴展AccessControlFilter

AccessControlFilter繼承了PathMatchingFilter,并擴展了了兩個方法:

public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {?

??? return isAccessAllowed(request, response, mappedValue)?

???? || onAccessDenied(request, response, mappedValue);?

}??

public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

return isAccessAllowed(request, response, mappedValue)

|| onAccessDenied(request, response, mappedValue);

}

isAccessAllowed:即是否允許訪問,返回true表示允許;

onAccessDenied:表示訪問拒絕時是否自己處理,如果返回true表示自己不處理且繼續攔截器鏈執行,返回false表示自己已經處理了(比如重定向到另一個頁面)。

public class MyAccessControlFilter extends AccessControlFilter {?

??? protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {?

??????? System.out.println("access allowed");?

??????? return true;?

??? }?

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

??????? System.out.println("訪問拒絕也不自己處理,繼續攔截器鏈的執行");?

??????? return true;?

??? }?

}??

public class MyAccessControlFilter extends AccessControlFilter {

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

System.out.println("access allowed");

return true;

}

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

System.out.println("訪問拒絕也不自己處理,繼續攔截器鏈的執行");

return true;

}

}

然后在shiro.ini中進行如下配置:

[filters]?

myFilter4=com.github.zhangkaitao.shiro.chapter8.web.filter.MyAccessControlFilter?

[urls]?

/**=myFilter4? [filters]

myFilter4=com.github.zhangkaitao.shiro.chapter8.web.filter.MyAccessControlFilter

[urls]

/**=myFilter4

5.基于表單登錄攔截器

之前我們已經使用過Shiro內置的基于表單登錄的攔截器了,此處自己做一個類似的基于表單登錄的攔截器。

public class FormLoginFilter extends PathMatchingFilter {

private String loginUrl = "/login.jsp";

private String successUrl = "/";

@Override

protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

if(SecurityUtils.getSubject().isAuthenticated()) {

return true;//已經登錄過

}

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse resp = (HttpServletResponse) response;

if(isLoginRequest(req)) {

if("post".equalsIgnoreCase(req.getMethod())) {//form表單提交

boolean loginSuccess = login(req); //登錄

if(loginSuccess) {

return redirectToSuccessUrl(req, resp);

}

}

return true;//繼續過濾器鏈

} else {//保存當前地址并重定向到登錄界面

saveRequestAndRedirectToLogin(req, resp);

return false;

}

}

private boolean redirectToSuccessUrl(HttpServletRequest req, HttpServletResponse resp) throws IOException {

WebUtils.redirectToSavedRequest(req, resp, successUrl);

return false;

}

private void saveRequestAndRedirectToLogin(HttpServletRequest req, HttpServletResponse resp) throws IOException {

WebUtils.saveRequest(req);

WebUtils.issueRedirect(req, resp, loginUrl);

}

private boolean login(HttpServletRequest req) {

String username = req.getParameter("username");

String password = req.getParameter("password");

try {

SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password));

} catch (Exception e) {

req.setAttribute("shiroLoginFailure", e.getClass());

return false;

}

return true;

}

private boolean isLoginRequest(HttpServletRequest req) {

return pathsMatch(loginUrl, WebUtils.getPathWithinApplication(req));

}

}

onPreHandle主要流程:

1、首先判斷是否已經登錄過了,如果已經登錄過了繼續攔截器鏈即可;

2、如果沒有登錄,看看是否是登錄請求,如果是get方法的登錄頁面請求,則繼續攔截器鏈(到請求頁面),否則如果是get方法的其他頁面請求則保存當前請求并重定向到登錄頁面;

3、如果是post方法的登錄頁面表單提交請求,則收集用戶名/密碼登錄即可,如果失敗了保存錯誤消息到“shiroLoginFailure”并返回到登錄頁面;

4、如果登錄成功了,且之前有保存的請求,則重定向到之前的這個請求,否則到默認的成功頁面。

shiro.ini配置

[filters]?

formLogin=com.github.zhangkaitao.shiro.chapter8.web.filter.FormLoginFilter?

[urls]?

/test.jsp=formLogin?

/login.jsp=formLogin??

[filters]

啟動服務器輸入http://localhost:8080/chapter8/test.jsp測試時,會自動跳轉到登錄頁面,登錄成功后又會跳回到test.jsp頁面。此處可以通過繼承AuthenticatingFilter實現,其提供了很多登錄相關的基礎代碼。另外可以參考Shiro內嵌的FormAuthenticationFilter的源碼,思路是一樣的。

6.任意角色授權攔截器

Shiro提供roles攔截器,其驗證用戶擁有所有角色,沒有提供驗證用戶擁有任意角色的攔截器。

public class AnyRolesFilter extends AccessControlFilter {?

??? private String unauthorizedUrl = "/unauthorized.jsp";?

??? private String loginUrl = "/login.jsp";?

??? protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {?

??????? String[] roles = (String[])mappedValue;?

??????? if(roles == null) {?

??????????? return true;//如果沒有設置角色參數,默認成功

??????? }?

??????? for(String role : roles) {?

??????????? if(getSubject(request, response).hasRole(role)) {?

??????????????? return true;?

??????????? }?

??????? }?

??????? return false;//跳到onAccessDenied處理

??? }?

@Override

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

??????? Subject subject = getSubject(request, response);?

??????? if (subject.getPrincipal() == null) {//表示沒有登錄,重定向到登錄頁面

??????????? saveRequest(request);?

??????????? WebUtils.issueRedirect(request, response, loginUrl);?

??????? } else {?

??????????? if (StringUtils.hasText(unauthorizedUrl)) {//如果有未授權頁面跳轉過去

??????????????? WebUtils.issueRedirect(request, response, unauthorizedUrl);?

??????????? } else {//否則返回401未授權狀態碼

??????????????? WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);?

??????????? }?

??????? }?

??????? return false;?

??? }?

}??

public class AnyRolesFilter extends AccessControlFilter {

private String unauthorizedUrl = "/unauthorized.jsp";

private String loginUrl = "/login.jsp";

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

String[] roles = (String[])mappedValue;

if(roles == null) {

return true;//如果沒有設置角色參數,默認成功

}

for(String role : roles) {

if(getSubject(request, response).hasRole(role)) {

return true;

}

}

return false;//跳到onAccessDenied處理

}

@Override

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

Subject subject = getSubject(request, response);

if (subject.getPrincipal() == null) {//表示沒有登錄,重定向到登錄頁面

saveRequest(request);

WebUtils.issueRedirect(request, response, loginUrl);

} else {

if (StringUtils.hasText(unauthorizedUrl)) {//如果有未授權頁面跳轉過去

WebUtils.issueRedirect(request, response, unauthorizedUrl);

} else {//否則返回401未授權狀態碼

WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);

}

}

return false;

}

}

流程:

1、首先判斷用戶有沒有任意角色,如果沒有返回false,將到onAccessDenied進行處理;

2、如果用戶沒有角色,接著判斷用戶有沒有登錄,如果沒有登錄先重定向到登錄;

3、如果用戶沒有角色且設置了未授權頁面(unauthorizedUrl),那么重定向到未授權頁面;否則直接返回401未授權錯誤碼。

shiro.ini配置

[filters]?

anyRoles=com.github.zhangkaitao.shiro.chapter8.web.filter.AnyRolesFilter?

[urls]?

/test.jsp=formLogin,anyRoles[admin,user]?

/login.jsp=formLogin??

[filters]

anyRoles=com.github.zhangkaitao.shiro.chapter8.web.filter.AnyRolesFilter

[urls]

/test.jsp=formLogin,anyRoles[admin,user]

/login.jsp=formLogin

此處可以繼承AuthorizationFilter實現,其提供了授權相關的基礎代碼。另外可以參考Shiro內嵌的RolesAuthorizationFilter的源碼,只是實現hasAllRoles邏輯。

8.4 默認攔截器

Shiro內置了很多默認的攔截器,比如身份驗證、授權等相關的。默認攔截器可以參考org.apache.shiro.web.filter.mgt.DefaultFilter中的枚舉攔截器:

默認攔截器名

攔截器類

說明(括號里的表示默認值)

身份驗證相關的

authc

org.apache.shiro.web.filter.authc

.FormAuthenticationFilter

基于表單的攔截器;如“/**=authc”,如果沒有登錄會跳到相應的登錄頁面登錄;主要屬性:usernameParam:表單提交的用戶名參數名( username);? passwordParam:表單提交的密碼參數名(password); rememberMeParam:表單提交的密碼參數名(rememberMe);? loginUrl:登錄頁面地址(/login.jsp);successUrl:登錄成功后的默認重定向地址; failureKeyAttribute:登錄失敗后錯誤信息存儲key(shiroLoginFailure);

authcBasic

org.apache.shiro.web.filter.authc

.BasicHttpAuthenticationFilter

Basic HTTP身份驗證攔截器,主要屬性: applicationName:彈出登錄框顯示的信息(application);

logout

org.apache.shiro.web.filter.authc

.LogoutFilter

退出攔截器,主要屬性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout”

user

org.apache.shiro.web.filter.authc

.UserFilter

用戶攔截器,用戶已經身份驗證/記住我登錄的都可;示例“/**=user”

anon

org.apache.shiro.web.filter.authc

.AnonymousFilter

匿名攔截器,即不需要登錄即可訪問;一般用于靜態資源過濾;示例“/static/**=anon”

授權相關的

roles

org.apache.shiro.web.filter.authz

.RolesAuthorizationFilter

角色授權攔截器,驗證用戶是否擁有所有角色;主要屬性: loginUrl:登錄頁面地址(/login.jsp);unauthorizedUrl:未授權后重定向的地址;示例“/admin/**=roles[admin]”

perms

org.apache.shiro.web.filter.authz

.PermissionsAuthorizationFilter

權限授權攔截器,驗證用戶是否擁有所有權限;屬性和roles一樣;示例“/user/**=perms["user:create"]”

port

org.apache.shiro.web.filter.authz

.PortFilter

端口攔截器,主要屬性:port(80):可以通過的端口;示例“/test= port[80]”,如果用戶訪問該頁面是非80,將自動將請求端口改為80并重定向到該80端口,其他路徑/參數等都一樣

rest

org.apache.shiro.web.filter.authz

.HttpMethodPermissionFilter

rest風格攔截器,自動根據請求方法構建權限字符串(GET=read, POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create)構建權限字符串;示例“/users=rest[user]”,會自動拼出“user:read,user:create,user:update,user:delete”權限字符串進行權限匹配(所有都得匹配,isPermittedAll);

ssl

org.apache.shiro.web.filter.authz

.SslFilter

SSL攔截器,只有請求協議是https才能通過;否則自動跳轉會https端口(443);其他和port攔截器一樣;

其他

noSessionCreation

org.apache.shiro.web.filter.session

.NoSessionCreationFilter

不創建會話攔截器,調用 subject.getSession(false)不會有什么問題,但是如果 subject.getSession(true)將拋出 DisabledSessionException異常;

另外還提供了一個org.apache.shiro.web.filter.authz.HostFilter,即主機攔截器,比如其提供了屬性:authorizedIps:已授權的ip地址,deniedIps:表示拒絕的ip地址,不過目前還沒有完全實現,不可用。

這些默認的攔截器會自動注冊,可以直接在ini配置文件中通過“攔截器名.屬性”設置其屬性:

perms.unauthorizedUrl=/unauthorized?

perms.unauthorizedUrl=/unauthorized

另外如果某個攔截器不想使用了可以直接通過如下配置直接禁用:

perms.enabled=false?

轉載于:https://www.cnblogs.com/pyrmkj/p/4462514.html

總結

以上是生活随笔為你收集整理的第8章 拦截器机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 热久久中文字幕 | 黑白配av| 黄色成人在线免费观看 | 国产精品伦一区二区 | 国产精品suv一区二区 | 欧美狂猛xxxxx乱大交3 | 少女忠诚电影高清免费 | 国产精品天美传媒 | 五月天婷婷丁香 | a天堂v| 亚洲自拍偷拍网 | 亚洲欧美在线视频 | 欧美专区 日韩专区 | 极品国产一区 | 亚洲免费看片 | 波多野结衣一区二区三区在线 | 神马久久精品 | 国产农村妇女精品一区二区 | 精品久久久久久中文字幕人妻最新 | 午夜精品福利电影 | www好男人| 国产精品久久久久野外 | 日韩久久久久久久久久 | 日韩一区二区三区在线免费观看 | 精品人妻无码一区二区三区换脸 | 欧美日韩一区二区视频在线观看 | 日韩一区二区免费播放 | www.日本黄色 | 亚洲国产精品成人va在线观看 | 67194成人在线| 亚洲AV成人无码久久精品巨臀 | 丰满人妻一区二区三区在线 | 亚洲色婷婷久久精品av蜜桃 | 99国产精品久久久久久久久久久 | 国产黄色网址在线观看 | 最新地址在线观看 | 欧美一区二区三区精品 | 国产高清精品在线观看 | 夜夜嗨av一区二区三区四区 | 亚洲va久久久噜噜噜无码久久 | 老女人乱淫 | 嫩草视频国产 | 国产3p在线播放 | 久草视频在线播放 | 亚洲熟区 | 手机看片一区二区三区 | 性欧美成人播放77777 | 特级西西人体444www高清大胆 | 九九热伊人 | 777国产成人入口 | 国产三级av在线播放 | 久久久成人精品 | 91色站 | 一本色道久久亚洲综合精品蜜桃 | 狠狠操天天干 | 国产精品呻吟 | 搞黄网站在线观看 | 海角社区在线视频播放观看 | www.夜夜夜 | 精品国产一区在线 | 美女搡bbb又爽又猛又黄www | 欧美中文字幕在线视频 | 丰满少妇xbxb毛片日本 | 日韩精品――中文字幕 | 成人在线综合网 | 在线观看污视频网站 | 色亚洲影院 | 美女视频黄a视频全免费观看 | 色综合久久久无码中文字幕波多 | 起碰在线 | 美国av大片 | 蜜桃视频一区二区在线观看 | 日韩a在线播放 | 午夜18视频在线观看 | 黄色av片三级三级三级免费看 | 久久久久久久久久av | 亚洲av女人18毛片水真多 | 成年人免费在线观看网站 | 亚洲精品66| 老牛影视av老牛影视av | 亚洲色欧美另类 | 日韩综合网| 欧洲美女毛片 | 日韩中文字幕视频在线观看 | 国产成人a∨ | 日韩啪啪网站 | 国产精品无套 | 在线亚洲欧美 | 欧美特黄一级视频 | 欧美性做爰猛烈叫床潮 | 超碰伊人网 | 在线亚洲人成电影网站色www | 美女靠逼视频网站 | 一区二区三区国产av | 中文字幕国产精品 | 葵司ssni-879在线播放 | 少妇高潮一区二区三区99刮毛 | 成人动态视频 | 可以免费看的av |