什么是shiro?
Shiro是apache旗下一個開源框架,它將軟件系統的安全認證相關的功能抽取出來,實現用戶身份認證,權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架。
為什么要用shiro?
既然可以基於url實現權限的管理,為什么還要用shiro呢??
1.shiro將安全認證相關的功能抽取出來組成一個框架,使用shiro就可以非常快速的完成認證、授權等功能的開發,降低系統成本。最主要的就是方便了我們的開發。
2.shiro使用廣泛,shiro可以運行在web應用,非web應用,集群分布式應用中越來越多的用戶開始使用shiro。
shiro認證
認證流程:
實例:
1.創建一個Java工程,並加入shiro-core的jar包以及它的依賴包。
2.自定義realm
Shiro有自帶的IniRealm,IniRealm從ini配置文件中讀取用戶的信息,大部分情況下需要從系統的數據庫中讀取用戶信息,所以需要自定義realm。
- public class CustomRealm extends AuthorizingRealm {
- @Override
- public String getName() {
- return "customRealm";
- }
- // 用於認證
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(
- AuthenticationToken token) throws AuthenticationException {
- // token是用戶輸入的
- // 第一步從token中取出身份信息
- String userCode = (String) token.getPrincipal();
- // 第二步:根據用戶輸入的userCode從數據庫中查詢
- // 模擬從數據庫查詢到密碼
- String password = "111111";
- // 如果查詢到返回認證信息AuthenticationInfo
- SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
- userCode, password, this.getName());
- return simpleAuthenticationInfo;
- }
- }
3.配置shiro-realm.ini文件
- [main]
- #自定義realm
- customRealm=cn.itcast.shiro.realm.CustomRealm
- #將realm設置到securityManager,相當於spring中注入
- securityManager.realms=$customRealm
4.創建認證代碼
- // 用戶登錄和退出
- @Test
- public void testCustomRealm() {
- // 創建securityManager工廠,通過ini配置文件創建securityManager工廠
- Factory<SecurityManager> factory = new IniSecurityManagerFactory(
- "classpath:shiro-realm.ini");
- // 通過工廠創建SecurityManager
- SecurityManager securityManager = factory.getInstance();
- // 將securityManager設置到運行環境中
- SecurityUtils.setSecurityManager(securityManager);
- // 創建一個Subject實例,該實例認證要使用上邊創建的securityManager進行
- Subject subject = SecurityUtils.getSubject();
- // 創建token令牌,記錄用戶認證的身份和憑證即賬號和密碼
- UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
- "111111");
- try {
- // 用戶登陸
- subject.login(token);
- } catch (AuthenticationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- // 用戶認證狀態
- Boolean isAuthenticated = subject.isAuthenticated();
- System.out.println("用戶認證狀態:" + isAuthenticated);
- // 用戶退出
- subject.logout();
- isAuthenticated = subject.isAuthenticated();
- System.out.println("用戶認證狀態:" + isAuthenticated);
- }
5.認證流程
(1)創建token令牌,token中有用戶提交的認證信息即賬號和密碼
(2)執行subject.login(token),最終由securityManager通過Authenticator進行認證
(3)Authenticator的實現ModularRealmAuthenticator調用realm從數據庫中取用戶真實的賬號和密碼
(4)CustomRealm先根據token中的賬號去數據庫中找該賬號,如果找不到則給ModularRealmAuthenticator返回null,如果找到則匹配密碼,匹配密碼成功則認證通過。
6.測試
登錄時用戶認證成功,退出時用戶認證失敗。
shiro授權
授權流程
授權方式
shiro支持三種方式的授權:
1.編程式
- Subject subject = SecurityUtils.getSubject();
- if(subject.hasPermission(“admin”)) {
- //有權限
- } else {
- //無權限
- }
2.注解式
- @RequiresPermissions("admin")
- public void hello() {
- //有權限
- }
3.JSP/GSP標簽
- <shiro:hasPermission name="admin">
- <!— 有權限—>
- </shiro:hasRole>
在web系統集成中使用后兩種方式,我在這兒舉個簡單的例子就用第一種方式了。
實例
1.自定義realm
- // 用於授權
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(
- PrincipalCollection principals) {
- // 獲取身份信息
- //將getPrimaryPrincipal方法返回值轉為真實身份類型(在上邊的doGetAuthenticationInfo認證通過填充到Simpl)
- String username = (String) principals.getPrimaryPrincipal();
- // 根據身份信息從數據庫中查詢權限數據
- // ....這里使用靜態數據模擬
- List<String> permissions = new ArrayList<String>();
- permissions.add("user:create");
- permissions.add("user:delete");
- // 將權限信息封閉為AuthorizationInfo
- SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
- for (String permission : permissions) {
- simpleAuthorizationInfo.addStringPermission(permission);
- }
- return simpleAuthorizationInfo;
- }
2.配置shiro-realm.ini文件與上面認證配置文件相同
3.創建授權代碼
- // 自定義realm進行資源授權測試
- @Test
- public void testAuthorizationCustomRealm() {
- // 從ini文件中創建SecurityManager工廠
- Factory<SecurityManager> factory = new IniSecurityManagerFactory(
- "classpath:shiro-realm.ini");
- // 創建SecurityManager
- SecurityManager securityManager = factory.getInstance();
- // 將securityManager設置到運行環境
- SecurityUtils.setSecurityManager(securityManager);
- // 創建主體對象
- Subject subject = SecurityUtils.getSubject();
- // 對主體對象進行認證
- // 用戶登陸
- // 設置用戶認證的身份(principals)和憑證(credentials)
- UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
- "111111");
- try {
- subject.login(token);
- } catch (AuthenticationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- // 用戶認證狀態
- Boolean isAuthenticated = subject.isAuthenticated();
- System.out.println("用戶認證狀態:" + isAuthenticated);
- // 授權檢測,失敗則拋出異常
- // subject.checkRole("role22");
- // 基於資源授權
- System.out.println("是否擁有某一個權限:" + subject.isPermitted("user:delete"));
- System.out.println("是否擁有多個權限:"
- + subject.isPermittedAll("user:update", "user:delete"));
- // 檢查權限
- subject.checkPermission("user:delete");
- }
4.授權流程
(1)執行subject.isPermitted("user:delete")
(2)securityManager通過ModularRealmAuthorizer進行授權
(3)ModularRealmAuthorizer調用realm獲取權限信息
(4)ModularRealmAuthorizer再通過permissionResolver解析權限字符串,校驗是否匹配
5.測試
表明該用戶擁有delete權限但是不擁有update權限。
轉載:http://blog.csdn.net/u010539352/article/details/51220276