Shiro安全框架的使用
Shiro安全框架
1.介紹
Shiro有三個核心的概念:Subject、SecurityManager和Realms。
Subject(主體):?subject本質上是當前正在執行的用戶的特定于安全的“view”。它也可以表示第三方服務、守護進程帳戶、cron作業或任何類似的東西——基本上是當前與軟件交互的任何東西。
SecurityManager(安全管理器): SecurityManager是Shiro架構的核心,它充當一種“傘形”對象,協調其內部安全組件,這些組件一起構成一個對象圖,一旦為應用程序配置了SecurityManager及其內部對象圖,通常就不需要再管它了,應用程序開發人員幾乎將所有時間都花在Subject API上
Realms(領域): realm充當Shiro和應用程序的安全數據之間的“橋梁”或“連接器”。 當需要與與安全相關的數據(如用戶帳戶)進行實際交互以執行身份驗證(登錄)和授權(訪問控制)時,Shiro會從一個或多個為應用程序配置的Realms中查找這些內容.類似于SpringMVC的DAO層
2.導入架包
在pom.xml中導入架包,使用SpringBoot來使用Shiro,采用的版本是<shiro.version>1.4.0</shiro.version>
<!--使用shiro安全框架--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>${shiro.version}</version></dependency> </dependencies>?
3.編寫Shiro配置文件
package com.example.demo.config; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.filter.authc.LogoutFilter; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map;@Configuration public class ShiroConfiguration {/**管理Shiro的生命周期*/ @Bean(name = "lifecycleBeanPostProcessor") public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor();}/**處理攔截請求,需要注入securityManager*/ @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ System.out.println("處理攔截請求"); ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean(); /*用工廠*/ shiroFilterFactoryBean.setSecurityManager(securityManager); /*默認跳轉界面*/ shiroFilterFactoryBean.setLoginUrl("/login.html"); /*登錄成功后跳轉界面*/ shiroFilterFactoryBean.setSuccessUrl("/index.html"); /*跳轉到未授權界面*/ shiroFilterFactoryBean.setUnauthorizedUrl("/test.html"); /*自定義攔截器,攔截動作次序與編寫時順序有關,確保最后進行'/**'的驗證操作,否則他之后的會攔截失效*/ Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //設置不需要訪問權限的界面,Resource和Controller訪問目錄為'/' filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/demo/test", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); //對所有的用戶進行認證,'authc'代表需要登錄,當所有的認證都通過的時候才可以訪問路徑, filterChainDefinitionMap.put("/**", "authc"); //退出攔截器,并對退出動作進行重定向 filterChainDefinitionMap.put("/logout", "logout"); LogoutFilter logoutFilter = new LogoutFilter(); logoutFilter.setRedirectUrl("/login.html"); //將自定義攔截器放入'shiroFilter'攔截器中 shiroFilterFactoryBean.getFilters().put("logout", logoutFilter); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }@Bean(name = "securityManager") public SecurityManager securityManager(EhCacheManager cacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //設置自己編寫的Realm,進行認證和授權操作 securityManager.setRealm(myShiroRealm()); securityManager.setCacheManager(cacheManager); return securityManager; }/**設置自己編寫的Realm,進行認證和授權操作,'MyShiroRealm'要另外編寫,* 進行認證和授權時會自動調用realm中的方法*/ @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; }/** * 憑證匹配器 (由于我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了 * 進行的加密操作 */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:這里使用MD5算法; hashedCredentialsMatcher.setHashIterations(2);// 散列的次數,比如散列兩次,相當于 // md5(md5("")); return hashedCredentialsMatcher; }/**配置緩存*/ @Bean public EhCacheManager getCacheManager(){ EhCacheManager ehCacheManager = new EhCacheManager(); ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml"); return ehCacheManager; } }?
4.緩存配置
<?xml version="1.0" encoding="UTF-8"?> <ehcache updateCheck="false" name="shiroCache"><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/> </ehcache>5.自定義Realm
在Shiro中,進行的授權和認證就是由它來操作的,認證操作時在登錄時通過Subject的login方法,將用戶名密碼傳入這里面,與數據里面進行交互,判斷是否存在此用戶或者密碼是否正確,存在則認證成功,主要有兩個方法
?
編寫一個工具類,來獲取當前的user或者session
package com.example.demo.utils; import com.example.demo.pojo.User; import org.apache.shiro.SecurityUtils; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; public class UserUtils {private static String login_user="login_user";public static void setUserSession(User user) {getSession().setAttribute(login_user, user);}public static Session getSession() {Subject currentUser = SecurityUtils.getSubject();Session session = currentUser.getSession();return session;}public static User getCurrentUser() {User user = (User) getSession().getAttribute(login_user);return user;} }
6.加密算法和獲取Session的方法
加密算法在Shiro配置文件中使用的是MD5,加密兩次,相應的login認證操作調用EncoderPassword()?方法時,兩者也應該一樣
在Service中編寫登錄認證的加密算法,這樣登錄認證時的加密后的密碼和數據庫中對應的一致
@Override public String EncoderPassword(String password, String salt) {//采取MD5算法進行加密,加密2次Object object = new SimpleHash("MD5", password, salt, 2);return object.toString(); }7.登錄操作
獲取到前端的用戶名和密碼,封裝在一個token里面,然后獲取當前的subject,調用它的login方法,參數傳入,然后它會調用到自定義realm中的認證操作,認證成功后返回數據
@RestController @RequestMapping(value = "/demo") public class DemoController {@RequestMapping("/test")public User index(User user) {//用于存取用戶名和密碼UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getName(), user.getPassword());//設置一個subjectSubject subject =SecurityUtils.getSubject();/*對這個subject對應的用戶名和密碼進行認證操作,若自己自定義了realm,會用自定義的realm記性*/subject.login(usernamePasswordToken);User user2=UserUtils.getCurrentUser();System.out.println(UserUtils.getCurrentUser().toString());return user2;} }?
8.授權操作
在realm中doGetAuthorizationInfo()中編寫,為認證后的用戶添加角色控制,在controller中或其他地方設置訪問權限,只有擁有權限的用戶方可進行相關操作,如下所示:
數據庫中角色定位2,那么只有
@RequestMapping("/role") //@RequiresAuthentication:只要授權就能就能進行訪問 @RequiresRoles(value = {"2","user"},logical = Logical.OR) //只要其中一個角色進行了進行了認證就行 public String Role(){Sysem.out.println("測試角色");return "regist.html"; }9.測試結果
登錄界面,默認跳轉界面
?
?
認證成功
?
點擊測試角色,動作為"/role"
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Shiro安全框架的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAS乐观锁原理
- 下一篇: 求二叉树最长路径长度和