首先什麼是shiro? shiro是apache下麵的一個開源項目,下麵是其網站上對其的一段說明: Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, aut
首先什麼是shiro?
shiro是apache下麵的一個開源項目,下麵是其網站上對其的一段說明:
Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.
弱弱的翻譯一下:apache shiro是一個強大且易於使用的java安全框架,使用它可以進行
1:認證
2:鑒權
3:加密
4:會話管理
通過shiro簡單易懂的api,可以簡單快速的為任何應用程式提供安全保護。
什麼是認證?
認證就是登陸一個系統之前,認證就是系統通過用戶的輸入去辨別登陸的用戶是誰,認證過程中,用戶需要提供一些輸入讓系統辨別且信任你。
The Shiro framework is designed to make authentication as clean and intuitive as possible while providing a rich set of features. Below is a highlight of the Shiro authentication features.
shiro框架在提供豐富功能的同時提供了直觀簡單的使用方式,下麵是shiro提供的幾種認證功能。
-
Subject Based - Almost everything you do in Shiro is based on the currently executing user, called a Subject. And you can easily retrieve the Subject anywhere in your code. This makes it easier for you to understand and work with Shiro in your applications.
Subjecet-在shiro中幾乎所有的操作都是基於當前指定的用戶,也稱為subject,在代碼的任何位置都可以輕易的訪問到subject,這使在你的項目中使用shiro變得更易於理解
-
Single Method call - The authentication process is a single method call. Needing only one method call keeps the API simple and your application code clean, saving you time and effort.
單個方法調用-認證過程僅僅是一個方法的調用,這讓你應用的代碼更加簡潔,給你節省了時間
- Rich Exception Hierarchy - Shiro offers a rich exception hierarchy to offered detailed explanations for why a login failed. The hierarchy can help you more easily diagnose code bugs or customer services issues related to authentication. In addition, the richness can help you create more complex authentication functionality if needed.
豐富的異常體系-shiro提供了豐富的異常以便於更加詳細的瞭解登陸失敗的原因,這些異常讓我們方便定位以及修改bug
- ‘Remember Me’ built in - Standard in the Shiro API is the ability to remember your users if they return to your application. You can offer a better user experience to your them with minimal development effort
remember me功能內置的支持:shiro中remember me功能的api可以給你應用更好的用戶體驗。
- Pluggable data sources -
Shiro uses pluggable data access objects (DAOs), called Realms, to
connect to security data sources like LDAP and Active Directory. To help
you avoid
building and maintaining integrations yourself, Shiro provides
out-of-the-box realms for popular data sources like LDAP, Active
Directory, Kerberos, and JDBC. If needed, you can also create your own
realms to support specific functionality not included in
the basic realms.
可
插拔的數據源-shiro使用被稱為Reamls的可插拔的數據連接對象來連接你的數據源,例如:LDAP,避免你自己去構建以及維護這些交
互,shiro內置提供了幾種常用的數據源接入機制,如果有必要,你可以自己創建特殊的Reaml來提供基礎Reamls所不支持的功能。
- Login with one or more realms - Using Shiro, you can easily authenticate a user against one or more realms and return one unified view of their identity. In addition, you can customize the authentication process with Shiro’s notion of an authentication strategy. The strategies can be setup in configuration files so changes don’t require source code modifications– reducing complexity and maintenance effort.
通過一個或者多個realms進行登錄認證-使用shiro可以輕易的認證一個用戶並提供一個統一的試圖,此外我們還可以定製化認 證的策略,我們可以在配置文件中進行配置而不必修改代碼。
什麼是鑒權?
鑒權也被成為許可權控制,判斷是否有許可權訪問某個資源,shiro對鑒權提供的支持:
-
Checks based on roles or permissions - Since the complexity of authorization differs greatly between applications, Shiro is designed to be flexible, supporting both role-based security and permission-based security based on your projects needs.
提供基於角色和許可權的方式進行鑒權
-
Powerful and intuitive permission syntax - As an option, Shiro provides an out-of-the-box permission syntax, called Wildcard Permissions, that help you model the fine grained access policies your application may have. By using Shiro’s Wildcard Permissions you get an easy-to-process and human readable syntax. Moreoever, you don’t have to go through the time-consuming effort and complexity of creating your own method for representing your access policies.
強大且直觀的許可權規則,shiro提供通配符進行許可權的校驗,使用通配符規則可讀性較高
-
Multiple enforcement options – Authorization checks in Shiro can be done through in-code checks, JDK 1.5 annotations, AOP, and JSP/GSP Taglibs. Shiro’s goal is to give you the choice to use the option you think are best based on your preferences and project needs.
多種鑒權方式可選,可以使用jdk1.5中的註解,aop或者jsp標簽
-
Strong caching support - Any of the modern open-source and/or enterprise caching products can be plugged in to Shiro to provide a fast and efficient user-experience. For authorization, caching is crucial for performance in larger environments or with more complex policies using back-end security data sources.
高效的緩存支持
-
Supports any data model - Shiro can support any data model for access control– it doesn’t force a model on you. Your realm implementation ultimately decides how your permissions and roles are grouped together and whether to return a “yes” or a “no” answer to Shiro. This feature allows you to architect your application in the manner you chose and Shiro will bend to support you.
支持任何類型的數據模型
再來看看shiro幾個關鍵的概念:
Subject:Subject我們在上面說過,Subject一般來說代表當前登錄的用戶,我們可以在自己的代碼中很容易的獲取到Subject對象
- Subject currentUser = SecurityUtils.getSubject();
獲得Subject對象之後我們可以通過Subject對象進行授權檢查。
- AuthenticationToken token = new UsernamePasswordToken(username, password);
- Subject.isPermitted()/checkRoles()
- Subject.login(token)//登錄操作
- Subject.logout()//退出登錄操作
SecurityManager:Subject 代表某一個用戶,而SecurityManager就是對這些Subject進行管理的對象,在web項目中使用shiro的時候,我們通常在xml文件 中配置好SecurityManager對象,然後就不會跟它打太多的交道,而僅僅是訪問Subject的api.
- //這裡我們使用spring和shiro進行集成
- <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- <property name="realm" ref="shiroDbRealm" />
- <property name="cacheManager" ref="shiroEhcacheManager" />
- </bean>
Realms:shiro中使用Realms這個概念表示與數據進行交互的那一層,封裝了數據源連接的細節,我們可以實現不同的realms來連接不同的數據源,通過realms讀取用戶數據用於認證和鑒權。
下麵我們使用shiro和spring集成,對web項目進行控制,shiro與spring的集成灰常的簡單。
在已經配置好的spring項目中,我們在xml中加入:
- <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>/*</url-pattern>
- </filter-mapping>
這 個時候我們可能想DelegatingFilterProxy是個什麼東東,難道這個就是shiro的入口麽?但是通過查看這個類是位於spring- web這個jar包中的,根本就不屬於shiro的一部分,那麼也不可能是shiro的入口,我們跟進去發現這個類繼承了抽象類 GenericFilterBean,而GenericFilterBean實現了Filter介面,應用程式啟動的時候應該會調用 GenericFilterBean.init()方法:該方法設置了filter的配置,另外調用了方法initFilterBean(),這個方法在 子類中進行實現。
DelegatingFilterProxy類中對initFilterBean方法進行了實現:
- @Override
- protected void initFilterBean() throws ServletException {
- synchronized (this.delegateMonitor) {
- if (this.delegate == null) {
- // If no target bean name specified, use filter name.
- if (this.targetBeanName == null) {
- this.targetBeanName = getFilterName();
- }
- // Fetch Spring root application context and initialize the delegate early,
- // if possible. If the root application context will be started after this
- // filter proxy, we'll have to resort to lazy initialization.
- WebApplicationContext wac = findWebApplicationContext();
- if (wac != null) {
- this.delegate = initDelegate(wac);
- }
- }
- }
- }
如果沒有設置targetBeanName屬性,那麼就使用過濾器的名字作為beanName
- <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
- <property name="securityManager" ref="securityManager" />
- <property name="loginUrl" value="/login" />
- <property name="successUrl" value="/management/index" />
- <property name="filters">
- <map>
- <!-- <entry key="authc" value-ref="baseFormAuthenticationFilter"/> -->
- <!-- 是否啟用驗證碼檢驗 -->
- <entry key="authc" value-ref="captchaFormAuthenticationFilter" />
- <entry key="user" value-ref="dWZUserFilter" />
- </map>
- </property>
- <property name="filterChainDefinitions">
- <value>
- /Captcha.jpg = anon
- /styles/** = anon
- /login/timeout = anon
- /login = authc
- /logout = logout
- /** = user
- </value>
- </property>
- </bean>
我們在web.xml中配置的過濾器名稱是shiroFilter,然後我們在spring的配置文件中以該名字配置一個bean
- <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- <property name="realm" ref="shiroDbRealm" />
- <!-- 緩存用戶的授權信息 -->
- <property name="cacheManager" ref="shiroEhcacheManager" />
- </bean>
- <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
- <property name="cacheManagerConfigFile" value="classpath:ehcache/ehcache-shiro.xml" />
- </bean>
- <bean id="shiroDbRealm" class="com.mbb.ShiroDbRealm" depends-on="userDAO, userRoleDAO, moduleDAO, organizationRoleDAO,captchaService">
- </bean>
ShiroDbRealm是我們自定義實現的realms用於查詢用戶數據。
- public class ShiroDbRealm extends AuthorizingRealm {
- //實現用戶的認證
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
- User user = userService.get(authcToken.getUsername());
- ShiroUser shiroUser = new ShiroUser(user.getId(), user.getUsername(), user);
- <pre code_snippet_id="239402" snippet_file_name="blog_20140316_8_5493693" name="code" class="html"> return new SimpleAuthenticationInfo(shiroUser, user.getPassword(),ByteSource.Util.bytes(salt), getName());
- </pre> }<br>
- //實現用戶的鑒權<br>
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {<br>
- Collection<?> collection = principals.fromRealm(getName());<br>
- if (CollectionUtils.isEmpty(collection)) {<br>
- return null;<br>
- }<br>
- ShiroUser shiroUser = (ShiroUser) collection.iterator().next();<br>
- <br>
- List<UserRole> userRoles = userRoleService.find(shiroUser.getId());<br>
- List<OrganizationRole> organizationRoles = organizationRoleService<br>
- .find(shiroUser.getUser().getOrganization().getId());<br>
- <br>
- SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();<br>
- info.addStringPermissions(makePermissions(userRoles, organizationRoles, shiroUser));<br>
- <br>
- return info;<br>
- }<br>
- }
- <pre></pre>
- <p></p>
- <pre></pre>
- <br>
- <br>
- <p></p>
- <p><br>
- </p>
- <br>
- <p></p>
- <ul style="">
- <br>
- </ul>
- <br>
- <p></p>