(3)shiro自定義realm
上面一章說到shiro的認證和授權最底層就是呼叫realm的getAuthorizationInfo(獲取使用者的角色和資源)和getAuthenticationInfo(校驗賬號密碼是否正確)兩個方法。
如果我們要從資料庫中查詢使用者和他的許可權資訊,我們可以使用shiro提供給我們的JdbcRealm
JdbcRealm
新增jar
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>0.2.23</version> </dependency>
classpath環境下新建shiro-jdbc.ini如下配置
這裡我們採用了阿里巴巴的資料來源,注入到jdbcRealm的dataSource變數中,並且將這個jdbcRealm注入到securityManager,有點類似於spring的注入。
下面的sql放在github上對應的章節根目錄下,匯入即可,資料庫密碼填寫自己資料庫密碼
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm dataSource=com.alibaba.druid.pool.DruidDataSource dataSource.driverClassName=com.mysql.jdbc.Driver dataSource.url=jdbc:mysql://localhost:3306/shiro dataSource.username=root dataSource.password=123456 jdbcRealm.dataSource=$dataSource #注入securityManager的realm securityManager.realms=$jdbcRealm
測試程式碼:
ShiroUtils.login("classpath:shiro-jdbc.ini","zhang","123456"); Subject subject = SecurityUtils.getSubject(); //是否通過認證 System.out.println(subject.isAuthenticated());
其中ShiroUtils的登入方法(這個以後直接略過):
public static void login(String configPath,String username,String password){ Factory<SecurityManager> factory =new IniSecurityManagerFactory(configPath); //得到安全管理器 SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); } catch (AuthenticationException e) { e.printStackTrace(); } }View Code
最後輸出true。
因為jdbcRealm裡面的sql都是固定的,所以我們表結構都要按照JdbcRealm裡面建立對應的表。下面是JdbcRealm裡面各種查詢的sql(salt是密碼加密,後面介紹加密再說,我們這裡直接用明文密碼)
表裡面數據分別如下
接著測試程式碼新增如下:
System.out.println(subject.hasRole("role1"));
System.out.println(subject.isPermitted("user:create"));
最後輸出true,false
為什麼角色role1獲取到了,permission沒有獲取到呢。
原因是JdbcRealm裡面有個permissionsLookupEnabled預設是false,所以不會查詢對應的資源許可權,我們在配置檔案中開啟這個查詢。
#開啟permission查詢 jdbcRealm.permissionsLookupEnabled=true
再查詢就是true了。
自定義Realm
1 新增MyRealm類直接繼承AuthorizingRealm.
public class MyRealm extends AuthorizingRealm { //認證資訊, @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); String password = new String(upToken.getPassword()); //模擬使用者名稱密碼是否正確 if(!"zhang".equals(username)){ throw new UnknownAccountException(); } if(!"123456".equals(password)){ throw new IncorrectCredentialsException(); } return new SimpleAuthenticationInfo(username,password,getName()); } //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //獲取使用者名稱 String username = (String)getAvailablePrincipal(principals); //模擬從資料庫查詢出來對應的角色和許可權 Set<String> roles = new HashSet<String>(); roles.add("role_1"); roles.add("role_2"); Set<String> permissions = new HashSet<String>(); permissions.add("user:create"); permissions.add("user:delete"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; } }
2,classpath檔案下新建shiro-myrealm.ini配置檔案
myrealm= com.nfcm.shiro.Realm.MyRealm
securityManager.realms=$myrealm
3,測試
ShiroUtils.login("classpath:shiro-myrealm.ini","zhang","123456"); Subject subject = SecurityUtils.getSubject(); //是否通過認證 System.out.println(subject.isAuthenticated()); //是否有role1角色 System.out.println(subject.hasRole("role_1")); System.out.println(subject.isPermitted("user:create"));
到這裡全部測試通過。
github程式碼地址
https://github.com/cmniefei/shiroparent