user.ini
[users] cheng = 123,admin [roles] admin = user:delete,user:update
IniRealmTest.java
package com.cheng.test; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; public class IniRealmTest { IniRealm iniRealm = new IniRealm("classpath:user.ini"); @Test public void testAuthentication() { // 1. 构建 SecurityManager 环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(iniRealm); // 2. 主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123"); subject.login(token); System.out.println("isAuthenticated: " + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:delete"); subject.checkPermission("user:update"); } }
JdbcRealm
JdbcRealm的方式访问数据库,通过与数据库的连接,验证相应的登录用户与授权。
jdbcRealm新建其实例,并初始化。
Maven中引入mysql的驱动以及相应数据源的类。
新建数据源作为成员变量,并且在静态快中初始化url、username、password等。
将数据源设置到到jdbcrealm中,并且将此realm设置到权限管理中。
之后进行登录等验证,jdbcrealm会在源码的地方写入了默认的进行认证与授权的sql语句,以及表名什么的都规定好了。如果想更改,则写入新的sql语句,并且调用jdbcrealm中的设置认证Query、设置权限Query、设置角色查询的方法,进行修改。
当查询权限的时候,会报错,即便库汇总有次权限,仍旧会报错,因为你需要在jdbcrealm中开启persimisson的为true即可:setPermissionsLookupEnabled(true)。(默认为false)
其他的与之前的认证与授权的步骤一致。
JdbcRealm 有默认的查询语句图
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>shiro-learn</artifactId> <groupId>com.cheng</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>shiro-test</artifactId> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
JdbcRealmTest.java
package com.cheng.test; import com.alibaba.druid.pool.DruidDataSource; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.jdbc.JdbcRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; public class JdbcRealmTest { DruidDataSource dataSource = new DruidDataSource(); { dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root"); dataSource.setPassword("zy159357"); } @Test public void testAuthentication() { JdbcRealm jdbcRealm = new JdbcRealm(); jdbcRealm.setDataSource(dataSource); // 查询权限数据,默认为 false jdbcRealm.setPermissionsLookupEnabled(true); String sql = "select password from test_user where user_name = ?"; jdbcRealm.setAuthenticationQuery(sql); String roleSql = "select role_name from test_user_role where user_name = ?"; jdbcRealm.setUserRolesQuery(roleSql); String permissionSql = "select permission_name from test_user_permission where role_name = ?"; jdbcRealm.setPermissionsQuery(permissionSql); // 1. 构建 SecurityManager 环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(jdbcRealm); // 2. 主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123"); subject.login(token); System.out.println("isAuthenticated: " + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkRoles("admin", "user"); subject.checkPermission("user:select"); } }
自定义Realm + 安全加密
CustomRealm.java
package com.cheng.shiro.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * 自定义 Realm */ public class CustomRealm extends AuthorizingRealm { Map<String, String> userMap = new HashMap<>(16); { userMap.put("cheng", "66f469382db2328c876b700deb336220"); super.setName("customRealm"); } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); Set<String> roles = getRolesByUserName(username); Set<String> permissions = getPermissionsByUsername(username); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.setRoles(roles); simpleAuthorizationInfo.setStringPermissions(permissions); return simpleAuthorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // 1. 从主体传过来的认证信息中,获得用户名 String username = (String) authenticationToken.getPrincipal(); // 2. 通过用户名到数据库中获取凭证 String password = getPasswordByUsername(username); if (password == null) { return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, "customRealm"); // 设置加密的 盐 authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("cheng")); return authenticationInfo; } private Set<String> getRolesByUserName(String username) { Set<String> set = new HashSet<>(); // 从数据库或者缓存中获取角色数据 set.add("admin"); set.add("user"); return set; } private Set<String> getPermissionsByUsername(String username) { Set<String> set = new HashSet<>(); set.add("user:delete"); set.add("user:update"); return set; } /** * 模拟数据库查询凭证 */ private String getPasswordByUsername(String username) { return userMap.get(username); } public static void main(String[] args) { // 密码 + 盐 加密后的结果 Md5Hash md5Hash = new Md5Hash("123", "cheng"); System.out.println(md5Hash.toString()); } }
CustomerRealmTest.java
package com.cheng.test; import com.cheng.shiro.realm.CustomRealm; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; import org.junit.Test; /** * 自定义 Realm */ public class CustomerRealmTest { @Test public void testAuthentication() { CustomRealm customRealm = new CustomRealm(); // 1. 构建 SecurityManager 环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(customRealm); // 加密 HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); // 加密算法名称 matcher.setHashAlgorithmName("md5"); // 加密次数 matcher.setHashIterations(1); // 自定义 Realm 中设置加密对象 customRealm.setCredentialsMatcher(matcher); // 2. 主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123"); subject.login(token); System.out.println("isAuthenticated: " + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:delete"); subject.checkPermission("user:update"); } }