自定义一个Realm
准备工作
自定义Realm一般直接继承AuthorizingRealm抽象类即可(里面包含身份认证与授权两个方法)
/**
* 自定义一个Realm
*/
public class MyRealm extends AuthorizingRealm {
//获取到这个Realm的名称(随便取)
@Override
public String getName() {
return "MyRealm";
}
//进行授权判断(权限)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//进行身份认证(登录)
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
身份认证
身份认证的代码
/**
* 自定义一个Realm
*/
public class MyRealm extends AuthorizingRealm {
//获取到这个Realm的名称(随便取)
@Override
public String getName() {
return "MyRealm";
}
//进行授权的认证
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//进行登录的认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//明显的知道:这个authenticationToken就是UsernamePasswordtoken
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername(); //拿到用户名(注:这个用户名是传过来的)
//这里根据用户名去获取密码(如果没有获取到,相当于这个用户不存在,就返回null值)
String password = getByName(username);
if(password==null){
return null;
}
//创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
return authenticationInfo;
}
//模拟从数据库中获取信息
private String getByName(String username) {
if("admin".equals(username)){
return "123456";
}else if("guest".equals(username)){
return "abcd";
}
return null;
}
}
测试
@Test
public void testMyRealm() throws Exception{
//创建自己定义的Realm
MyRealm myRealm = new MyRealm();
//把Realm放到securityManager中去
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(myRealm);
//把权限管理器放到相应的环境中(我们可以在项目任何位置拿到)
SecurityUtils.setSecurityManager(securityManager);
//拿到当前用户(Subject就是当前用户,游客)
Subject currentUser = SecurityUtils.getSubject();
//准备登录的令牌(准备用户名与密码)
UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");
try {
//根据令牌进行功能登录(当前用户进行登录)
currentUser.login(token);
} catch (UnknownAccountException e) {
System.out.println("这个账号不存在!" + token.getPrincipal());
e.printStackTrace();
} catch (IncorrectCredentialsException ice) {
System.out.println("这个密码不存在!" + token.getPrincipal());
ice.printStackTrace();
}catch (AuthenticationException e){
System.out.println("i don't k");
}
}
授权
授权代码
public class MyRealm extends AuthorizingRealm {
//获取到这个Realm的名称(随便取)
@Override
public String getName() {
return "MyRealm";
}
//进行授权的认证
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//拿到认证的主要信息(用户名)
String username = (String) principalCollection.getPrimaryPrincipal();
//模拟根据用户名拿到角色信息与权限信息
Set<String> roles = getRolesByUsername(username);
Set<String> permissions = getPermissionsByUsername(username);
//拿到验证信息对象
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//设置用户的角色
authorizationInfo.setRoles(roles);
//设置用户的权限
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
//模拟根据用户名拿到角色的功能
private Set<String> getRolesByUsername(String username) {
Set<String> roles = new HashSet<>();
roles.add("admin");
roles.add("it");
return roles;
}
//模拟根据用户名拿到权限的功能
private Set<String> getPermissionsByUsername(String username) {
Set<String> permissions = new HashSet<>();
permissions.add("employee.*");
permissions.add("department.save");
return permissions;
}
...
}
授权测试
System.out.println("是否是这个角色:"+currentUser.hasRole("admin"));
System.out.println("是否是拥有权限:"+currentUser.isPermitted("employee.save"));
密码加密
shiro中的加密
/**
* algorithmName:加密算法(md5,sha)
* source:原始密码
* salt,加盐
* hashIterations:遍历次数
*/
SimpleHash simpleHash = new SimpleHash("MD5","admin","aijiejieya",10);
System.out.println(simpleHash);
测试时自定义Realm加上算法
//设置咱们Realm的密码匹配器(我们的密码要怎么处理)
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5"); //匹配器使用MD5的算法
matcher.setHashIterations(10);//加密算法要迭代多少次
myRealm.setCredentialsMatcher(matcher);
加上盐值
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//明显的知道:这个authenticationToken就是UsernamePasswordtoken
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername(); //拿到用户名(注:这个用户名是传过来的)
//这里根据用户名去获取密码(如果没有获取到,相当于这个用户不存在,就返回陪我)
String password = getByName(username);
if(password==null){
return null;
}
//在这里加盐值需一个ByteSource对象,而Shiro提供了一个ByteSource对象给咱们
ByteSource salt = ByteSource.Util.bytes("aijiejieya");
//创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
return authenticationInfo;
}
private String getByName(String username) {
if("admin".equals(username)){
// 4a95737b032e98a50c056c41f2fa9ec6: 123456 迭代10次不加盐的结果
// 831d092d59f6e305ebcfa77e05135eac: 123456 迭代10次加盐(itsource)的结果
return "831d092d59f6e305ebcfa77e05135eac"; //修改为加密加盐后的数据
}else if("guest".equals(username)){
return "abcd";
}
return null;
}
小结
Realm的用法我们已经基本掌握了,也就是shiro这个框架基本用法我们也就掌握了!
既然shiro是一个框架 那肯定是要和Spring集成的!那如何来集成Spring呢!下一篇讲!!