前言
接 Shiro自定义RealmAnd散列算法
ini 文件当中配置散列
相关配置内容如下所示:
代码语言:txt复制[main]
# 定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
# 散列算法
credentialsMatcher.hashAlgorithmName=md5
# 散列次数
credentialsMatcher.hashIterations=3
# 指定realm
myRealm=com.yby6.realm.MyRealm
# 配置散列
myRealm.credentialsMatcher=$credentialsMatcher
# 配置自定义散列
securityManager.realms=$myRealm
要保证存储在数据库中的密码是经过散列之后的,不然认证器进行认证的时候是通过你定义的规则去进行认证的,而你数据库存储的不一致会导致不成功,假如你设置认证的相关信息为盐为 yby6 而数据库中已经存储的密码是通过 JonathanTang 盐值进行加密存储的,你登录的时候认证器去验证的时候就会导致双方不一致,所以数据库中存储的信息需要和你认证器设置的规则加密之后的信息一致才行。
首先我们自己使用 MD5 规则加密一串密文出来。
代码语言:txt复制@Test
public void encryption() {
SimpleHash simpleHash = new SimpleHash("md5", "1234", "it6666", 3);
System.out.println(simpleHash);
}
代码语言:txt复制80abd6b3faad22acb16bc1a11da51b2e
然后更改我们自定义的 Realm,更改之后的内容如下所示:
代码语言:txt复制public class MyRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 获取用户名
String username = (String) token.getPrincipal();
// 假如以下定义的用户名和密码是从数据库中查询出来的,实际中需要注入Dao去数据库中进行查询然后进行验证查询出来的信息是否合法
String myName = "yby6";
String password = "80abd6b3faad22acb16bc1a11da51b2e";
// 如果输入的名称不和数据库查询出来的一致
if (!myName.equals(username)) {
return null;
}
// 如果等于,交给认证器去认证即可我们就无须关心了
return new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes("yby6"), this.getName());
}
}
什么是授权
● 授权,即访问控制,控制谁能访问哪些资源。
● 主体进行身份认证后需要分配权限,方可访问系统的资源,对于某些资源没有权限是无法访问的这就是授权。
使用 ini 的形式配置权限信息
● 在 ini 文件中设置用户、角色、权限的配置规则。
● 用户名=密码,角色1,角色2 ...
● 首先根据用户名找角色,再根据角色找权限,角色是权限集合。
● 权限字符串的规则
○ “资源标识符:操作:资源实例标识符”
○ 对哪个资源的哪个实例具有什么操作。
○ : 是资源 / 操作 / 实例的分割符。
○ 权限字符串也可以使用 * 通配符。
如下将给出一个配置示例如下所示,修改 shiro.ini:
代码语言:txt复制[users]
#用户yby6的密码是1234,此用户具有role1和role2两个角色
#用户yangbuyiya的密码是1234,此用户具有role2一个角色
yby6=1234,role1,role2
yangbuyiya=1234,role2
[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create、delete权限
role2=user:create,user:delete
#角色role3对资源user拥有create权限
role3=user:create
自定义 Realm 的形式权限
修改 MyRealm.java
代码语言:txt复制@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取身份信息
Object principal = principals.getPrimaryPrincipal();
// 根据用户名查询该用户的角色和权限
List<String> roles = new ArrayList<>();
roles.add("role1");
roles.add("role2");
List<String> permissions = new ArrayList<>();
permissions.add("user:create");
permissions.add("user:delete");
// 把角色和权限与 subject 关联在一起,然后进行返回
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
然后修改之前的测试类,具体修改的内容或者新增的内容如下代码所示, 在认证成功之后才去做授权, 判断当前的用户是否有某一个角色和某一个权限
代码语言:txt复制public class Demo {
public static void main(String[] args) {
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("yby6", "12345");
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
e.printStackTrace();
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误");
e.printStackTrace();
}
System.out.println("是否认证" subject.isAuthenticated());
subject.logout();
System.out.println("是否认证" subject.isAuthenticated());
// 判断当前用户有没有角色1
System.out.println(subject.hasRole("role1"));
// 判断当前用户是否同时具备多个角色
System.out.println(subject.hasAllRoles(Arrays.asList("role1", "role3")));
// 判断是否有某一个权限
System.out.println(subject.isPermitted("user:create"));
// 判断是否同时有多个权限
System.out.println(subject.isPermittedAll("user:create", "user:update"));
}
}