shiro | Spring security |
---|---|
粗粒度 | 细粒度 |
功能够用 | 功能更细更多 |
学习难度低 | 学习难度高 |
Shiro四大基石
名称 | 意思 |
---|---|
Authentication | 身份验证:登录--- 噢搜体k森 |
Authorization | 授权:权限判断 ---- 噢搜锐z森 |
Cryptography | 密码学:加密 |
Session Management | 会话管理:session |
会话管理:
用户登录,会把用户名和密码传到后台,后台会去数据库中找有没有这个人,如果有登录成功,会存在session中(通过HttpSession。web项目中才有,CS中就没有这个类了)。但是这里session提供了这个功能,不用在考虑有没有HttpSession
核心类
- Subject(啥不j可特)---当前用户(游客/登录用户)如果要登录需要令牌
- SecurityManager (C可瑞 麦泥着)---- Shiro的权限管理器【Shiro所有功能都是通过他】(最重要)
- Reaim(入母) ---- 去拿到登录等的值【拿数据、获取数据】
Shiro官方有所有案例
我们现在用的是SpringMVC所以使用路径判断xue微好一点
其实两个方式都差不多,都可以用,Controller.save()是Struts2好一点
权限表关系(重)
- 用户----角色 --- 多对多 【一个人有多个角色,一个角色有多个人】
- 角色-----权限----多对多 【一个角色有多个功能,一个功能对应多个角色】
速成案例
1.新建maven项目
2.导jar包
<!--shiro支持包-->
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--日志支持包-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!--测试包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3.导入shiro.ini 文件
一、获取SecurityManager对象
1.获取Shiro.ini文件
2.从工厂中获取到SecurityManager对象
二、把SecurityManager对象设置到上下文中
三、获取到当前用户(如果没有登录就是游客)
1.判断短是否登录----isAuthenicated()
2.如果没有登录就让他登录
①登录需要令牌----UsernamePasswordToken
②根据令牌实现登录
3,注销登录 ---- login()
4.try一下 如果输错报出错误
①Unknown(未知的)Account(账号)Exception---账户错误
②Incorrect(错误的)Credentials(凭证)Exception--密码错误
③AuthenicationException----最大的错误(神秘错误)
hasRole() ------ 判断是否是存在角色(返回true、false)角色判断
image.pngisPermitted() ------ 判断是否有该权限(返回true/false)权限判断
image.png定义一个自己的Realm 继承extends AuthorizingRealm
继承完就要实现两个方法 一个授权一个登陆
完成版
public class ShiroTest {
@Test
public void ShiroTest() throws Exception{
//拿到SecurityManager核心对象
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
//把SecurityManager对象放到当前的上下文中
SecurityUtils.setSecurityManager(securityManager);
//拿到当前用户
Subject subject = SecurityUtils.getSubject();
//获得令牌 ---- 判断
//④.如果没有登录,让他登录(需要令牌)
if(!subject.isAuthenticated()){
try {
//用户名密码令牌
AuthenticationToken token = new UsernamePasswordToken("root","123456");
//登录功能
subject.login(token);
} catch (UnknownAccountException e) {//Unknown(未知)Account(账号)Exception
e.printStackTrace();
System.out.println("用户名错误!");
} catch (IncorrectCredentialsException e) {//Incorrect(不正确的)Credentials(凭证;证书)Exception
e.printStackTrace();
System.out.println("密码错误!");
}catch (AuthenticationException e){
e.printStackTrace();
System.out.println("出现一个神迷的错误!!!!");
}
}
//对于角色的判断
System.out.println("是否是admin角色:"+subject.hasRole("admin"));
System.out.println("是否是it角色:"+subject.hasRole("it"));
//判断相应的权限
System.out.println("是否是employee:save权限:"+subject.isPermitted("employee:save"));
System.out.println("是否是employee:update权限:"+subject.isPermitted("employee:update"));
System.out.println("是否是department:save权限:"+subject.isPermitted("department:save"));
//判断这个用户是否登录
System.out.println("是否登录:" + subject.isAuthenticated());
//注销,退出,登出
subject.logout();
System.out.println("是否登录:" + subject.isAuthenticated());
}
}
上面都是在用Shiro.ini文件代替数据库玩的。现在开始用数据库来操作
案例2:自定义Realm
身份认证的代码
/**
* 自定义一个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
//1.拿到闸门的令牌(用户名密码Token)--把令牌强转成用户名密码令牌
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername(); //2.拿到用户名(注:这个用户名是传过来的)
//3.这里根据用户名到数据库中去获取密码(如果没有获取到,相当于这个用户不存在,就返回null值)
String password = getByName(username);
if(password==null){//判断如果password为空,那就返回空
//3.返回空就是代表用户名不存在,shiro会自动帮你报UnknowAcctountException
return null;
}
//创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
//4.传的是数据库密码:他要把这个密码和令牌中的密码做比较,如果对应不上,就会报IncorrectCredentialsException
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
//参数(主体(一般是当前用户名),密码,realm名字)--- 除了密码,其他都随意写
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();
//拿到SecurityManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//把Realm放到securityManager中去
securityManager.setRealm(myRealm);
//把SecurityManager放到上下文章
//把权限管理器放到相应的环境中(我们可以在项目任何位置拿到)
SecurityUtils.setSecurityManager(securityManager);
//拿到当前用户(Subject就是当前用户,游客)
Subject currentUser = SecurityUtils.getSubject();
//判断一下是否登录
System.out.println(""+ currentUser.isAuthenticated());
//准备登录的令牌(准备用户名与密码)
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");
}
}
授权(权限功能)
就是上面自定义Realm的时候,授权没有写,先搞得身份认证。现在回去在搞授权
密码加密(Shiro---密码学)
简单地说就是把看的懂得密码改成看不懂的
知识点
1.CS/BS :
CS是qq,画图板等等,通过软件 --------- BS就是webqq,通过页面展示出来的
2.粗粒度/细粒度:
粗粒度比如能不能添加用户,能不能删除用户。 --------细粒度就是在粗粒度能完成的的功能下还能在精细一点。功能更完美一点
java育儿园里的小学生“磨陀货”友情提供!!!
请大家尊重原创,如要转载,请注明出处:
转载自:https://www.jianshu.com/p/606e67f7cd1a,谢谢!!
有任何疑问,欢迎加入Java交流群458443587(加群时请备注)
网友评论