SPRingMVC整合Shiro,Shiro是一個強大易用的java安全框架,提供了認(rèn)證、授權(quán)、加密和會話管理等功能。
第一步:配置web.xml
<!-- 配置Shiro過濾器,先讓Shiro過濾系統(tǒng)接收到的請求 --> <!-- 這里filter-name必須對應(yīng)applicationContext.xml中定義的<bean id="shiroFilter"/> --> <!-- 使用[/*]匹配所有請求,保證所有的可控請求都經(jīng)過Shiro的過濾 --> <!-- 通常會將此filter-mapping放置到最前面(即其他filter-mapping前面),以保證它是過濾器鏈中第一個起作用的 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <!-- 該值缺省為false,表示生命周期由SpringApplicationContext管理,設(shè)置為true則表示由ServletContainer管理 --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
或者
<!-- apache shiro權(quán)限 --><filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
第二步:配置applicationContext-shiro.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <description>Shiro 配置</description><!-- Shiro主過濾器本身功能十分強大,其強大之處就在于它支持任何基于URL路徑表達(dá)式的、自定義的過濾器的執(zhí)行 --> <!-- Web應(yīng)用中,Shiro可控制的Web請求必須經(jīng)過Shiro主過濾器的攔截,Shiro對基于Spring的Web應(yīng)用提供了完美的支持 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- Shiro的核心安全接口,這個屬性是必須的 --> <property name="securityManager" ref="securityManager" /> <!-- 要求登錄時的鏈接(可根據(jù)項目的URL進行替換),非必須的屬性,默認(rèn)會自動尋找Web工程根目錄下的"/login.jsp"頁面 --> <property name="loginUrl" value="/login.jsp" /><!-- <property name="successUrl" value="/login.jsp" />--><!-- 登錄成功后要跳轉(zhuǎn)的連接(本例中此屬性用不到,因為登錄成功后的處理邏輯在LoginController里硬編碼為main.jsp了) --> <!-- <property name="successUrl" value="/system/main"/> --> <!-- 用戶訪問未對其授權(quán)的資源時,所顯示的連接 --> <!-- 若想更明顯的測試此屬性可以修改它的值,如unauthor.jsp,然后用[玄玉]登錄后訪問/admin/listUser.jsp就看見瀏覽器會顯示unauthor.jsp --> <property name="unauthorizedUrl" value="/error.jsp" /><!-- Shiro連接約束配置,即過濾鏈的定義 --> <!-- 此處可配合我的這篇文章來理解各個過濾連的作用http://blog.csdn.net/jadyer/article/details/12172839 --> <!-- 下面value值的第一個'/'代表的路徑是相對于HttpServletRequest.getContextPath()的值來的 --> <!-- anon:它對應(yīng)的過濾器里面是空的,什么都沒做,這里.do和.jsp后面的*表示參數(shù),比方說login.jsp?main這種 --> <!-- authc:該過濾器下的頁面必須驗證后才能訪問,它是Shiro內(nèi)置的一個攔截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter --> <property name="filterChainDefinitions"><value>/login.jsp* = anon/login.do* = anon/logout.do* = anon/index.jsp*= anon/image.jsp*= anon/error.jsp*= anon/*.jpg* = anon/*.png* = anon/*.CSS* = anon/*.js* = anon/*.jsp* = authc/*.do* = authc<!-- /user/*=authc,roles[1]/department/*=authc,roles[1]--></value></property></bean><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><!--設(shè)置自定義realm --><property name="realm" ref="monitorRealm" /></bean><!-- Support Shiro 所謂的異常攔截 可有可無 Annotation --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">/error</prop> </props> </property> </bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /><!--自定義Realm 繼承自AuthorizingRealm --><!-- 繼承自AuthorizingRealm的自定義Realm,即指定Shiro驗證用戶登錄的類為自定義的ShiroDbRealm.java --> <bean id="monitorRealm" class="com.dt.service.MonitorRealm"> <!-- 關(guān)閉授權(quán)緩存域,把authorizationCachingEnabled設(shè)置為false 否則會提示No cache or cacheManager properties have been set. Authorization cache cannot be obtained. --> <property name="authorizationCachingEnabled" value="false"/> </bean><!-- securityManager --><beanclass="org.springframework.beans.factory.config.MethodInvokingFactoryBean"><property name="staticMethod"value="org.apache.shiro.SecurityUtils.setSecurityManager" /><property name="arguments" ref="securityManager" /></bean><!-- Enable Shiro Annotations for Spring-configured beans. Only run after --><!-- the lifecycleBeanProcessor has run: --><beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor" /><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager" /></bean></beans>
第三步:自定義的Realm類
@Service("monitorRealm")public class MonitorRealm extends AuthorizingRealm {@Resourceprivate UserService userService;public MonitorRealm() {super();}//Authorization:授權(quán),即權(quán)限驗證,驗證某個已認(rèn)證的用戶是否擁有某個權(quán)限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細(xì)粒度的驗證某個用戶對某個資源是否具有某個權(quán)限;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {/* 這里編寫授權(quán)代碼 */HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); User user2 = (User)request.getsession().getAttribute("currentUser");/* 角色 */Set<String> roleNames = new HashSet<String>(); roleNames.add(String.valueOf(user2.getRoleId())); /* 權(quán)限 */ Set<String> permissions = new HashSet<String>(); permissions.addAll(PrivilegeReader.getModulUrlsById(user2.getRoleId())); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roleNames);//添加角色(Set集合<字符串>)info.setStringPermissions(permissions);return info;}// Authentication 身份認(rèn)證/登錄,驗證用戶是不是擁有相應(yīng)的身份;@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {/* 這里編寫認(rèn)證代碼 */UsernamePassWordToken token = (UsernamePasswordToken) authcToken;//User user = securityApplication.findby(upToken.getUsername());//User user = new User();//user.setUserName(token.getUsername());User user = userService.loadById(token.getUsername());if (user != null) {this.setSession("currentUser", user); return new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), user.getTrueName());}else{throw new AuthenticationException();}}//清空緩存public void clearCachedAuthorizationInfo(String principal) {SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());clearCachedAuthorizationInfo(principals);} /** * 將一些數(shù)據(jù)放到ShiroSession中,以便于其它地方使用 * @see 比如Controller,使用時直接用HttpSession.getAttribute(key)就可以取到 */ private void setSession(Object key, Object value){ Subject currentUser = SecurityUtils.getSubject(); if(null != currentUser){ Session session = currentUser.getSession(); if(null != session){ session.setAttribute(key, value); } } } }
第四步:SpringMvc
<!-- 使用注解的包,包括子集 --><context:component-scan base-package="com.dt.controller" /><!-- shiro 使用注解必須 --><context:annotation-config/><!-- Required for security annotations to work in this servlet --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/> <!-- Enable annotation-based controllers using @Controller annotations --> <bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> <bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> <!-- 視圖解析器 --><bean id="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/" /><property name="suffix" value=".jsp"></property></bean> <!-- 文件上傳 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8" /> <property name="maxUploadSize" value="10485760000" /> <property name="maxInMemorySize" value="40960" /></bean>
新聞熱點
疑難解答