参考链接:Shiro入门教程
1.shiro认证
1.1 shiro认证流程
· 1.2. shiro认证入门程序。
新建 shiro-first.ini通过此配置文件创建securityManager工厂。
#对用户信息进行配置,未自定义义Realm
[users]
#用户账号和密码
zhangsan=111111
lisi=222222
[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=2
#自定义realm,如果自定义了Realm,[users]会失效
customerRealm=com.lx.Shiro.CustomRealm
#将凭证匹配器设置到realm
customerRealm.credentialsMatcher=$credentialsMatcher
#将realm设置到securityManager,相当于spring注入额
securityManager.realms=$customerRealm
1.3.提交认证
public void iniTest() throws UnsupportedEncodingException {
URL url = MyShiroTest.class.getResource("../../../../resources/shiro-first.ini");
String s = url.toString().replaceAll("%20", " ");
String decode = URLDecoder.decode(s, "utf-8");
IniSecurityManagerFactory securityManagerFactory = new IniSecurityManagerFactory(decode);
SecurityUtils.setSecurityManager(securityManagerFactory.getInstance());
//从SecurityUtils里边创建一个subject
Subject subject = SecurityUtils.getSubject();
//在认证提交前准备token(令牌)
UsernamePasswordToken token = new UsernamePasswordToken("lisi_md5", "111111");
try {
//执行认证提交
subject.login(token);
} catch (AuthenticationException e) {
System.out.println(e);
}
//是否认证通过
boolean isAuthenticated = subject.isAuthenticated();
System.out.println("是否认证通过:" + isAuthenticated);
}
2.shiro授权
2.1授权流程
2.2授权方式
shiro支持三种方式的授权:
- 编程式:通过写if/else授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
//有权限
}else{
//无权限
}
- 注解方式:通过在执行的java 方法上放置相应的注解完成;
@RequiresRoles("admin")
public void hello(){
//有权限
}
- jsp标签: 在jsp页面通过相应的标签完成:
<shiro:hasRole name="admin">
<!-- 有权限 -->
</shiro:hasRole>
2.3 新建 shiro-permission.ini
创建存放权限的配置文件shiro-permission.ini,里面的内容相当于在数据库里面
[users]
#用户zhang的密码是123,此用户具有role1和role2两个角色
zhang=123,role1,role2
wang=123,role2
#如果自定了Realm[roles]会失效
[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
2.4 权限测试
@Test
public void iniTest() throws UnsupportedEncodingException {
URL url = MyShiroTest.class.getResource("../../../../resources/shiro-first.ini");
String s = url.toString().replaceAll("%20", " ");
String decode = URLDecoder.decode(s, "utf-8");
IniSecurityManagerFactory securityManagerFactory = new IniSecurityManagerFactory(decode);
SecurityUtils.setSecurityManager(securityManagerFactory.getInstance());
//从SecurityUtils里边创建一个subject
Subject subject = SecurityUtils.getSubject();
//在认证提交前准备token(令牌)
UsernamePasswordToken token = new UsernamePasswordToken("lisi_md5", "111111");
try {
//执行认证提交
subject.login(token);
} catch (AuthenticationException e) {
System.out.println(e);
}
//是否认证通过
boolean isAuthenticated = subject.isAuthenticated();
System.out.println("是否认证通过:" + isAuthenticated);
// 是否有某一个角色
System.out.println("用户是否拥有一个角色:" + subject.hasRole("role1"));
// 是否有多个角色
System.out.println("用户是否拥有多个角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));
// 基于资源授权
System.out.println("是否拥有某一个权限:" + subject.isPermitted("user:delete"));
System.out.println("是否拥有多个权限:" + subject.isPermittedAll("user:create:1", "user:delete"));
//退出操作
subject.logout();
}
自定义的Relam
public class CustomRealm extends AuthorizingRealm {
static Map<String, String> userPassMap = new HashMap<>();
static {
userPassMap.put("lisi", "111111");
userPassMap.put("lisi_md5", "36f2dfa24d0a9fa97276abbe13e596fc_qwerty");
}
/**
* 授权
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取身份信息
String username = (String) principals.getPrimaryPrincipal();
// 根据身份信息从数据库中查询权限数据
//....这里使用静态数据模拟
List<String> permissions = new ArrayList<String>();
permissions.add("user:create");
permissions.add("user:delete");
//将权限信息封闭为AuthorizationInfo
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 模拟数据库查询角色信息
Set<String> roles = new HashSet<>();
roles.add("role1");
simpleAuthorizationInfo.setRoles(roles);
for(String permission:permissions){
simpleAuthorizationInfo.addStringPermission(permission);
}
return simpleAuthorizationInfo;
}
/**
* 认证
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// token是用户输入的
// 第一步从token中取出身份信息
String userCode = (String) token.getPrincipal();
// 模拟从数据库查询到密码
if (!userPassMap.containsKey(userCode)) {
return null;
}
SimpleAuthenticationInfo simpleAuthenticationInfo = null;
String password = userPassMap.get(userCode);
if (password.contains("_")) {
// 模拟从数据库查询到密码,散列值
String pw = password.split("_")[0];
// 从数据库获取salt
String salt = password.split("_")[1];
simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, pw, ByteSource.Util.bytes(salt), getName());
} else {
simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password, getName());
}
return simpleAuthenticationInfo;
}
}