Shiro数据源有三种,一种是IniRealm(配置文件数据源)、一种是JdbcRealm(数据库数据源)、一种是自定义Realm。
综下所述,所谓的数据源,就是提供真实的用户名、密码、角色、权限,具体的验证逻辑由Shiro进行。
一、IniRealm(配置文件数据源)
(一)创建user.ini
[users]
root=root,admin
[roles]
admin=user:delete
(二)进行用户、角色、权限验证
public class IniRealmTest {
@Test
public void testIniRealm(){
//1、创建SecurityManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、创建IniRealm数据源(相当于用户名、密码、权限配置文件)
IniRealm realm = new IniRealm("classpath:user.ini");
//3、设置数据源
securityManager.setRealm(realm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("root", "root", "admin");
subject.login(token);
System.out.println();
//验证该用户是否有该角色
subject.checkRole("admin");
//验证该用户是否有该权限
subject.checkPermission("user:delete");
}
}
二、JdbcRealm(数据库数据源)
1、要想进行权限验证,必须进行该项设置:jdbcRealm.setPermissionsLookupEnabled(true)
2、JdbcRealm提供默认的用户、角色、权限查询语句,但是要求建的表名、列名必须和默认查询语句保持一致,否则就需要自定义查询语句,具体参见下方代码!
public class JdbcRealmTest {
private static DruidDataSource dataSource;
static {
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/shiro");
dataSource.setUsername("root");
dataSource.setPassword("root");
}
@Test
public void testJdbcRealm(){
//1、初始化JdbcRealm
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
/**
* 重点:JdbcRealm默认不开启权限检查,若要判断某角色是否有某样权限,需要开启此设置,否则会由于无法检查权限表,
* 导致查询到的权限为空。
*/
jdbcRealm.setPermissionsLookupEnabled(true);
//(1)自定义查询密码(若不自定义,JdbcRealm有默认查询语句)
String authenticationQuery = "select password from users where username = ?";
jdbcRealm.setAuthenticationQuery(authenticationQuery);
//(2)自定义查询角色(若不自定义,JdbcRealm有默认查询语句)
String userRolesQuery = "select role_name from user_roles where username = ?";
jdbcRealm.setUserRolesQuery(userRolesQuery);
//(3)自定义查询权限(若不自定义,JdbcRealm有默认查询语句)
String permissionsQuery = "select permission from roles_permissions where role_name = ?";
jdbcRealm.setPermissionsQuery(permissionsQuery);
//2、创建SecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//3、设置数据源
securityManager.setRealm(jdbcRealm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("root", "root");
subject.login(token);
System.out.println(subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
三、自定义Realm
1、创建自定义数据源类CustomRealm
public class CustomRealm extends AuthorizingRealm {
private Map<String, String> userMap = new HashMap<String, String>();
{
userMap.put("root", "root");
userMap.put("mark", "1234");
//设置数据源的名称
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 authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
/**
* 认证验证(返回数据库中真实的用户名、密码)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String)token.getPrincipal();
String password = getPasswordByUsername(username);
if (password == null){
return null;
}
//参数一:用户名 参数二:密码 参数三:自定义Realm的名称(在构造函数中设置名称super.setName("customRealm"))
return new SimpleAuthenticationInfo(username, password, "customRealm");
}
private String getPasswordByUsername(String username){
return userMap.get(username);
}
private Set<String> getRolesByUsername(String username){
Set<String> roles = new HashSet<String>();
roles.add("admin");
roles.add("guest");
return roles;
}
private Set<String> getPermissionsByUsername(String username){
Set<String> permissions = new HashSet<String>();
permissions.add("user:delete");
permissions.add("user:update");
return permissions;
}
}
2、测试
public class CustomRealmTest {
@Test
public void testCustomRealm(){
CustomRealm customRealm = new CustomRealm();
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(customRealm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("root", "root");
subject.login(token);
System.out.println(subject.isAuthenticated());
subject.checkRoles("admin", "guest");
subject.checkPermission("user:delete");
}
}