-
inirealm查看全部
-
記錄查看全部
-
produces="application/json;charset=utf-8"
查看全部 -
shiro官方架構(gòu)圖:http://shiro.apache.org/architecture.html
查看全部 -
Shiro緩存管理
其緩存管理仍舊是依賴(lài)于Redis進(jìn)行實(shí)現(xiàn)。
意為將從數(shù)據(jù)庫(kù)取出來(lái)的數(shù)據(jù)放置到Redis緩存中去,如果緩存中有直接取出,沒(méi)有則去數(shù)據(jù)庫(kù)中獲取并且放置到Reids緩存中。
步驟:
與之前的Session管理一致。首先創(chuàng)建CacheManager并且實(shí)現(xiàn)CacheManager接口。
創(chuàng)建Cache類(lèi)實(shí)現(xiàn)Cache接口,其中有增刪改查等方法。同樣通過(guò)序列化與反序列化、二進(jìn)制數(shù)組鍵值對(duì)等實(shí)現(xiàn)其中方法。
在CacheManager類(lèi)中注入Cache類(lèi),并且將其作為返回值寫(xiě)入到實(shí)現(xiàn)的唯一方法的返回處。
將CacheManager在Spring.xml中進(jìn)行配置Bean,并且將次設(shè)置到SecurityManager中。
都是通過(guò)JedisUtil完成的操作,均是將數(shù)據(jù)保存到了Redis中,無(wú)論是Session還是緩存只是多了一個(gè)Redis進(jìn)行管理。
查看全部 -
Shiro會(huì)話管理
其會(huì)話管理主要涉及到了Shiro整體框架的SessionManager與SessionDao模塊。
視頻中講的是與Redis相結(jié)合,進(jìn)行對(duì)Session的增刪改查操作。
當(dāng)然Shiro管理Session還可以通過(guò)別的介質(zhì)進(jìn)行管理。
步驟如下:
先加載Redis,在Maven 的pom.xml文件中配置Redis依賴(lài)包,坐標(biāo)如下:
<dependency> ????<groupId>redis.clients</groupId> ????<artifactId>jedis</artifactId> ????<version>2.7.3</version> </dependency>
配置Spring與Redis結(jié)合的配置文件。新建立Spring-redis.xml文件。
由于之前也沒(méi)接觸過(guò)Redis,這里只能重復(fù)視頻中的配置。配置JedisPool的bean,
其中設(shè)置屬性jedisPoolConfig、host、port信息,其中JedisPoolConfig則需要另外建立bean,然后將此Bean引入到JedisPool中,host則寫(xiě)本機(jī)地址,port一般為6379.當(dāng)然以上的類(lèi)都是Redis包下的,Redis是依靠Jedis來(lái)實(shí)現(xiàn)其功能。然后將此文件導(dǎo)入到Spring.xml主文件中,即采用import標(biāo)簽。
注意:需要下載相應(yīng)redis server,程序啟動(dòng)的時(shí)候,要先啟動(dòng)redis server,否則會(huì)報(bào)錯(cuò)。
新建util包,建立JedisUtil類(lèi),此類(lèi)中主要是對(duì)Redis進(jìn)行增刪改查操作。因?yàn)镽eids是存放鍵值對(duì)的形式。在JedisUtil中,將JedisPool注入到類(lèi)中,寫(xiě)入單獨(dú)方法獲取Jedis,即通過(guò)JedisPool.getResource()來(lái)獲取Jedis,此方法用于獲取Jedis對(duì)象,通過(guò)Jedis進(jìn)行直接對(duì)Redis存放值進(jìn)行增刪改查操作。
創(chuàng)建Shiro中SessionDao類(lèi),實(shí)現(xiàn)AbstractSessionDao,實(shí)現(xiàn)其中的增刪改查、獲取當(dāng)前活躍的Session等方法。由于redis中存放的是key與value都是二進(jìn)制的數(shù)組形式,所以在修改Redis值的時(shí)候需要注意將其轉(zhuǎn)成二進(jìn)制的數(shù)據(jù),并且判斷是否存在相應(yīng)id、session等。
其中:generateSessionId(session) 生成Serializable序列化的sessionId
? ? ? ? ? assignSessionId(session,sessionId) 綁定session與相應(yīng)的Id值
? ? ? ? ? session.getId 返回的是SessionId值,同理也是Serializable的類(lèi)型
? ? ? ? ? ? ? ? ?SerializationUtils.serialize (session) 通過(guò)序列化將session轉(zhuǎn)成相應(yīng)的byte[]數(shù)組
? ? ? ? ? ? ? ? ?SerializationUtils.deserialize(byte[]) 通過(guò)反序列化將字節(jié)轉(zhuǎn)成Object類(lèi)型,可通過(guò)強(qiáng)轉(zhuǎn)獲取? ? ? ? ? ? ? ? ? ?Session對(duì)象.
? ? ?PS:注意session 與 sessionId是否為空的情況判斷。另外如果加入前綴,可以在搜索的時(shí)候加入前綴+“*”代表搜索前綴是aa的所有匹配的key值。
6.同樣JedisUtils中也需要通過(guò)Jedis 的get put expire del keys方法進(jìn)行獲取 存儲(chǔ) 設(shè)置等待時(shí)間 刪除操作、查詢(xún)匹配key的值集合。
7.新建類(lèi)SessionManager 繼承 DefaultWebSessionManager類(lèi),里面可以什么都不做。
8.在spring.xml文件中,寫(xiě)入SessionManager的Bean 并且寫(xiě)入Sessiondao的bean,將SessionDao的Bean 注入到Sessionmanager中。最后將SessionManager的Bean注入到SecurityManager中即可。
9.此處將5-1與5-2整合在一起了,5-2的例子就不單獨(dú)寫(xiě)了。
? 此處在測(cè)試過(guò)程中,發(fā)現(xiàn)系統(tǒng)會(huì)讀取Session多次。
? 需要在SessionManager中重寫(xiě),retrieveSession方法。
? a.先通過(guò)參數(shù)SessionKey獲取sessionId,然后判斷sessionkey是否為websessionkey,如果是則通過(guò)強(qiáng)轉(zhuǎn)將其轉(zhuǎn)為WebSessionKey并且獲取ServletRequest。
b.核心是將SessionId 與 Session 放到Reqeust中,如果Request有,則直接拿去,沒(méi)有在去Redis中拿,如此一來(lái)則減少了訪問(wèn)Redis的次數(shù),減輕了Reids 的壓力。此時(shí)判斷request是否為空以及sessionId是否為空,如果同時(shí)都不為,則通過(guò)sessionId 從request的屬性中獲取Session,在判斷Session是否為空,如果不是空,則返回。
c.當(dāng)不符合以上條件時(shí)候,直接調(diào)用父類(lèi)的方法獲取Session,繼續(xù)判斷request是否為空,如果不是空,則將session和sessionId放入到request的屬性中即可,方便下次再來(lái)尋找直接從request中拿出,不用再多次訪問(wèn)Redis了。
查看全部 -
Shiro自動(dòng)登錄,意為記住密碼。將用戶(hù)名與密碼記錄在Cookie中。
主要通過(guò)配置來(lái)實(shí)現(xiàn)自動(dòng)登錄。步驟:
在Spring.xml文件中進(jìn)行配置,配置CookieRememberMeManager,并且利用屬性cookie,將外邊的bean的SimpleCookie注入進(jìn)去。SimpleCookie用構(gòu)造方法設(shè)置名稱(chēng),之后通過(guò)屬性用maxAge設(shè)置超時(shí)時(shí)間即可。
在登錄的時(shí)候,傳入U(xiǎn)serNameAndPassowrdToken的時(shí)候,其對(duì)象可以設(shè)置setRememberMe的屬性,為true即為記住登錄。
查看全部 -
Shiro過(guò)濾器
內(nèi)建過(guò)濾器:roles[a,b,c] 必須權(quán)限都符合才可以、perms[a,b,c]必須權(quán)限同時(shí)具備才可以。
anon 代表無(wú)需權(quán)限
authc 代表需要認(rèn)證才能訪問(wèn)
user 代表需要存在用戶(hù)對(duì)象才能被訪問(wèn)
logout 登錄退出才能被訪問(wèn)
perms 擁有權(quán)限才能被訪問(wèn)
roles 擁有角色才能被訪問(wèn)
port 相應(yīng)端口號(hào)才能訪問(wèn)
自定義,分認(rèn)證與授權(quán),如果是認(rèn)證則繼承認(rèn)證的類(lèi),如果是授權(quán)則繼承授權(quán)的類(lèi)。然后重寫(xiě)方法,其中參數(shù)Object o 即代表存在哪些參數(shù),即perms[a,b,c]中的abc然后判斷返回結(jié)果true 或者false即可。
在后臺(tái)xml文件中引入該filter的bean,然后在主過(guò)濾器中引入filter的標(biāo)簽,寫(xiě)入entry key 與 value-ref,然后在filter過(guò)濾中
filterChainDefinitions地方按照之前的規(guī)則使用該自定義過(guò)濾,寫(xiě)入
key值即可。
查看全部 -
Shiro通過(guò)注解配置授權(quán)
引入maven配置,如下:
<dependency> ????<groupId>org.aspectj</groupId> ????<artifactId>aspectjweaver</artifactId> ????<version>1.8.9</version> </dependency>
在springmvc.xml文件中開(kāi)啟aop配置,然后引入bean配置,將權(quán)限管理注入到Author的bean中即可。
配置如下;
<aop:config?proxy-target-class="true"/> <bean?class="org.apache.shiro.spring.LifecycleBeanPostProcessor"?id="lifecycleBeanPostProcessor"/> <bean?class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" ???id="authorizationAttributeSourceAdvisor"> ????????<property?name="securityManager"?ref="securityManager"/> </bean>
在需要角色或者權(quán)限的方法中引入@RequireRoles或者@RequirePersmisson來(lái)判斷。
查看全部 -
shiro集成Spring的數(shù)據(jù)庫(kù)連接
步驟:
先從pom.xml文件中引入三個(gè)包:mysql的驅(qū)動(dòng)包、spring-jdbc包、druid的數(shù)據(jù)源包。
在spring下建立spring-dao.xml文件。建立數(shù)據(jù)源的bean,即DruidDataSource類(lèi),并且將屬性u(píng)rl、username、password設(shè)置值。其次建立jdbctemplate的bean,將數(shù)據(jù)源注入到相應(yīng)的bean中。
創(chuàng)建dao層包,按照分層結(jié)構(gòu),分dao接口層以及dao.impl的實(shí)現(xiàn)類(lèi)層。寫(xiě)入U(xiǎn)serDao以及實(shí)現(xiàn)類(lèi)。
在spring.xml文件中使用impor標(biāo)簽導(dǎo)入spring-dao.xml文件,以及掃描com.imooc下的所有文件,把新加的注解掃描上。
調(diào)用jdbcTemplate方式:直接使用注解@Resource調(diào)動(dòng),同理調(diào)用接口也是此種方式注入。
實(shí)現(xiàn)類(lèi)必須加入@Compont否則無(wú)法被掃描到。接口可以不加入。
jdbcTemplate.query方法參數(shù)1sql語(yǔ)句2數(shù)組參數(shù)3RowMapper重寫(xiě)方法mapRow通過(guò)方法體的參數(shù)ResultSet來(lái)獲取對(duì)應(yīng)字段的查詢(xún)值即可。
修改Realm獲取值的方式,并且在相應(yīng)的Controller做判斷。
查看全部 -
Shiro集成Spring,步驟以及注意事項(xiàng)如下:
創(chuàng)建Maven的Web項(xiàng)目,創(chuàng)建完畢之后,按照Maven的規(guī)范創(chuàng)建出相應(yīng)的Java源碼文件以及相應(yīng)的test測(cè)試目錄。并且將web-info下的文件刪除。
設(shè)置java文件夾以及resources文件夾分別為源碼類(lèi)型以及資源文件類(lèi)型,具體可以點(diǎn)擊文件夾右鍵,找到Mark Dirctory as選擇。
在resources中創(chuàng)建spring文件夾,并且創(chuàng)建spring.xml以及spring-mvc.xml文件。
在web-info中創(chuàng)建web.xml文件。一般的idea不可創(chuàng)建出web.xml文件,所以此時(shí)按照網(wǎng)上給的方法,直接選擇菜單中的File---Project Stru----Facts 第一個(gè)空白點(diǎn)擊處,添加web.xml文件。點(diǎn)擊確定即可。路徑要寫(xiě)對(duì),是在web-info下。此種方法如果不行,則需要手動(dòng)寫(xiě)入web.xml文件。
web.xml代碼如下:
<?xml?version="1.0"?encoding="UTF-8"?> <web-app?xmlns="http://xmlns.jcp.org/xml/ns/javaee" ?????????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ?????????xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee?http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" ?????????version="3.1"> ????<!--?指定Spring?Bean的配置文件所在目錄。默認(rèn)配置在WEB-INF目錄下?--> ????<context-param> ????????<param-name>contextConfigLocation</param-name> ????????<param-value>classpath*:spring/spring.xml</param-value> ????</context-param> ????<listener> ????????<listener-class> ????????????org.springframework.web.context.ContextLoaderListener ????????</listener-class> ????</listener> ????<listener> ????????<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> ????</listener> ????<filter> ????????<filter-name>shiroFilter</filter-name> ????????<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> ????</filter> ????<filter-mapping> ????????<filter-name>shiroFilter</filter-name> ????????<url-pattern>/*</url-pattern> ????</filter-mapping> ????<servlet> ????????<servlet-name>dispatcherServlet</servlet-name> ????????<servlet-class> ????????????org.springframework.web.servlet.DispatcherServlet ????????</servlet-class> ????????<init-param> ????????????<param-name>contextConfigLocation</param-name> ????????????<param-value>classpath*:spring/spring-mvc.xml</param-value> ????????</init-param> ????????<load-on-startup>1</load-on-startup> ????</servlet> ????<servlet-mapping> ????????<servlet-name>dispatcherServlet</servlet-name> ????????<url-pattern>/</url-pattern> ????</servlet-mapping> </web-app>
其次在Maven的pom.xml文件中引入相應(yīng)的spring、springmvc 、shiro 、shiro-spring、shiro-web的jar包,注意必須版本保持匹配,否則啟動(dòng)容易報(bào)404錯(cuò)誤,我就是因?yàn)檫@個(gè)問(wèn)題。如下是pom.xml文件引入的包:
<dependency> ????<groupId>org.springframework</groupId> ????<artifactId>spring-context</artifactId> ????<version>4.2.4.RELEASE</version> </dependency> <!--?2)SpringWeb?Dependency?--> <dependency> ????<groupId>org.springframework</groupId> ????<artifactId>spring-webmvc</artifactId> ????<version>4.2.4.RELEASE</version> </dependency> <!--?3)Shiro?Dependency?--> <dependency> ????<groupId>org.apache.shiro</groupId> ????<artifactId>shiro-core</artifactId> ????<version>1.4.0</version> </dependency> <!--?4)ShiroWeb?Dependency?--> <dependency> ????<groupId>org.apache.shiro</groupId> ????<artifactId>shiro-web</artifactId> ????<version>1.4.0</version> </dependency> <!--?5)ShiroSpring?Dependency?--> <dependency> ????<groupId>org.apache.shiro</groupId> ????<artifactId>shiro-spring</artifactId> ????<version>1.4.0</version> </dependency>
在相應(yīng)的resources資源文件下建立spring文件夾,在spring-mvc.xml文件中寫(xiě)入掃描文件以及驅(qū)動(dòng)、過(guò)濾的標(biāo)簽,如下:
<context:component-scan?base-package="com.imooc.controller"/> <mvc:annotation-driven?/> <mvc:resources?mapping="/*"?location="/"/>
在spring.xml文件中,寫(xiě)入相應(yīng)的自定義的Realm的bean標(biāo)簽、加密的Hashed的bean標(biāo)簽(注入到Realm中)、寫(xiě)入默認(rèn)的web的權(quán)限管理的bean標(biāo)簽(注入Realm)、寫(xiě)入ShiroFilterFactoryBean的bean標(biāo)簽(將web的權(quán)限管理注入進(jìn)去)即可。
此外ShiroFilter的bean標(biāo)簽里面,還可以規(guī)定loginurl的值,即登錄的頁(yè)面,unauthor..登錄失敗沒(méi)權(quán)限訪問(wèn)的頁(yè)面,filterChainDefinitions過(guò)濾鏈,(過(guò)濾鏈里面可以以a=b的形式進(jìn)行過(guò)濾,例:/login.html = anon 表示在訪問(wèn)login.html頁(yè)面的時(shí)候不需要任何權(quán)限,anon表示無(wú)需權(quán)限,authc代表必須認(rèn)證通過(guò)才能訪問(wèn),一般鏈?zhǔn)菑纳贤缕ヅ?,只要匹配的相?yīng)結(jié)果,則直接返回。所以一般把/*=authc放在最后。)下面是源碼:
<bean?id="shiroFilter"?class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> ?????<property?name="securityManager"?ref="securityManager"/> ????<property?name="loginUrl"?value="login.html"/> ????<property?name="unauthorizedUrl"?value="403.html"/> ????<property?name="filterChainDefinitions"> ????????<value> ????????????/login.html?=?anon ????????????/subLogin?=?anon ????????????/*?=?authc ????????</value> ????</property> </bean> <bean?id="securityManager"?class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> ????<property?name="realm"?ref="customRealm"/> </bean> <bean?id="customRealm"?class="com.imooc.realm.CustomRealm"> ?????<property?name="credentialsMatcher"?ref="hashedCredentialsMatcher"/> </bean> <bean?id="hashedCredentialsMatcher"?class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> ????<property?name="hashAlgorithmName"?value="md5"/> ????<property?name="hashIterations"?value="1"/> </bean>
之后基本上就是寫(xiě)入controller以及html網(wǎng)頁(yè)即可。之后啟動(dòng)tomcat自動(dòng)訪問(wèn),其中關(guān)于編碼的問(wèn)題需要在@RequestMapping中設(shè)置produces="application/json;charset=utf-8"的形式即可。
查看全部 -
繼承?AuthorizatrionFilter?自定義Filter,
isAccessAllowed?用來(lái)校驗(yàn)權(quán)限 ,?其中的Object?就是filter?定義時(shí)后面中括號(hào)里的字符串 ,?如 perms[sys:delete,user:add]?里面的部分,?
查看全部 -
Shiro加密
通過(guò)HashedCredentialsMaster的方式加密,創(chuàng)建對(duì)象,并設(shè)置加密次數(shù)以及加密名稱(chēng),將此加密對(duì)象設(shè)置到Realm的setCredentialsMaster的方法中,即該Realm采用此密碼加密的方式。
后臺(tái)的密碼采用MD5的Hash碼值來(lái)存儲(chǔ)。如果想將密碼轉(zhuǎn)成MD5Hash碼可以采用MD5Hash對(duì)象,在構(gòu)造方法中寫(xiě)入密碼,
打印輸出其對(duì)象的toString方法即時(shí)期hash碼值。
加鹽,實(shí)際為在密碼中加入相應(yīng)的其他名稱(chēng)拼接在一起,組成一個(gè)新的密碼。如果想存儲(chǔ)加鹽之后的Hash碼,仍舊采用MD5Hash對(duì)象,在構(gòu)造方法的第二個(gè)參數(shù)中加入鹽的名稱(chēng),同樣打印toString方法即可顯示出來(lái)。其次在自定義的Realm認(rèn)證方法中,返回Simple之前,設(shè)置Simple的加鹽名稱(chēng),即采用setCredentailSalt方法寫(xiě)入鹽的名稱(chēng)即可。
以上兩種加密方式,對(duì)Realm改動(dòng)較小,除非加鹽才改動(dòng)。
在自定義的Realm加鹽的時(shí)候,需要將字符值轉(zhuǎn)成相應(yīng)的ByteSource,則需要用ByteSource.Util.bytes(字符)即可,將此值設(shè)置到Simple的返回值中。
查看全部 -
自定義的Realm,主要注意一下幾個(gè)步驟:
首先繼承并實(shí)現(xiàn)類(lèi)AuthorizingRealm的方法。其中方法
doGetAuthenticationInfo 主要做認(rèn)證操作,即可以通過(guò)獲取其中的
用戶(hù)名,查詢(xún)出相應(yīng)的密碼,然后將用戶(hù)名與密碼一并返回,shiro會(huì)自動(dòng)根據(jù)傳入的用戶(hù)名與密碼與此Realm返回的用戶(hù)名和密碼作比對(duì),返回你想要的結(jié)果。同理doGetAuthorizationInfo主要是用來(lái)做角色與權(quán)限的驗(yàn)證,也是通過(guò)用戶(hù)名,從數(shù)據(jù)庫(kù)中查找到相應(yīng)的角色或者權(quán)限的數(shù)據(jù)并返回一個(gè)Simple的授權(quán)類(lèi),授權(quán)系統(tǒng)會(huì)根據(jù)傳入的參數(shù)與返回的結(jié)果集對(duì)比,存在返回true不存在則拋異常。
兩者方法只能獲取用戶(hù)名稱(chēng),通過(guò)用戶(hù)名稱(chēng)連接數(shù)據(jù)庫(kù)獲取其他信息。這里只是做數(shù)據(jù)準(zhǔn)備操作,并不做判斷是否傳入的值與其相符的操作,此操作在此之后進(jìn)行。
根據(jù)兩者的返回對(duì)象分別返回Simple類(lèi)型的對(duì)象。認(rèn)證的對(duì)象需要將你獲取的用戶(hù)名和密碼放到構(gòu)造方法中。授權(quán)的對(duì)象需要你set到相應(yīng)的方法中。
例子中只是從本地寫(xiě)死靜態(tài)類(lèi),之后必須寫(xiě)入相應(yīng)的數(shù)據(jù)庫(kù)連接。
查看全部 -
JdbcRealm的方式訪問(wèn)數(shù)據(jù)庫(kù),通過(guò)與數(shù)據(jù)庫(kù)的連接,驗(yàn)證相應(yīng)的登錄用戶(hù)與授權(quán)。
jdbcRealm新建其實(shí)例,并初始化。
Maven中引入mysql的驅(qū)動(dòng)以及相應(yīng)數(shù)據(jù)源的類(lèi)。
新建數(shù)據(jù)源作為成員變量,并且在靜態(tài)快中初始化url、username、password等。
將數(shù)據(jù)源設(shè)置到到j(luò)dbcrealm中,并且將此realm設(shè)置到權(quán)限管理中。
之后進(jìn)行登錄等驗(yàn)證,jdbcrealm會(huì)在源碼的地方寫(xiě)入了默認(rèn)的進(jìn)行認(rèn)證與授權(quán)的sql語(yǔ)句,以及表名什么的都規(guī)定好了。如果想更改,則寫(xiě)入新的sql語(yǔ)句,并且調(diào)用jdbcrealm中的設(shè)置認(rèn)證Query、設(shè)置權(quán)限Query、設(shè)置角色查詢(xún)的方法,進(jìn)行修改。
當(dāng)查詢(xún)權(quán)限的時(shí)候,會(huì)報(bào)錯(cuò),即便庫(kù)匯總有次權(quán)限,仍舊會(huì)報(bào)錯(cuò),因?yàn)槟阈枰趈dbcrealm中開(kāi)啟persimisson的為true即可。
其他的與之前的認(rèn)證與授權(quán)的步驟一致。
Maven的配置:
<dependency> ????<groupId>mysql</groupId> ????<artifactId>mysql-connector-java</artifactId> ????<version>5.1.45</version> </dependency> <dependency> ????<groupId>com.alibaba</groupId> ????<artifactId>druid</artifactId> ????<version>1.0.12</version> </dependency>
查看全部
舉報(bào)