由于权限管理模块一般都是在资源一层,如果更深一层的话,则可能会与业务代码进行耦合,故提倡Shiro做权限管理,Spring官网也是用Shiro进行的权限管理。
AuthenticationTest.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.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser() {
simpleAccountRealm.addAccount("cheng", "123", "admin", "user");
}
@Test
public void testAuthentication() {
// 1. 构建 SecurityManager 环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
// 2. 主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123");
subject.login(token);
System.out.println("isAuthenticated: " + subject.isAuthenticated());
// 检查用户是否有 admin 角色
subject.checkRoles("admin", "user");
// 退出认证
subject.logout();
System.out.println("isAuthenticated: " + subject.isAuthenticated());
}
}
Shiro的IniRealm 形式:此形式主要是将数据存放到相应的user.ini即文件系统中,通过给定的格式,从文件中查找相应的数据是否存在。
步骤:
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 有默认的查询语句图
pom.xml
shiro-learn
com.cheng
1.0-SNAPSHOT
4.0.0
shiro-test
org.apache.shiro
shiro-core
1.4.0
mysql
mysql-connector-java
5.1.46
com.alibaba
druid
1.1.6
junit
junit
4.12
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");
}
}
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 userMap = new HashMap<>(16);
{
userMap.put("cheng", "66f469382db2328c876b700deb336220");
super.setName("customRealm");
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
Set roles = getRolesByUserName(username);
Set 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 getRolesByUserName(String username) {
Set set = new HashSet<>();
// 从数据库或者缓存中获取角色数据
set.add("admin");
set.add("user");
return set;
}
private Set getPermissionsByUsername(String username) {
Set 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");
}
}
下载地址:https://download.csdn.net/download/dream_weave/10892755
更多教程:Shiro - Spring + Jedis(会话、缓存、自动登录)整合篇