maven坐标:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
建立自定义 Realm,编写认证和授权方法
public class MyRealm extends AuthorizingRealm{
//授权方法:获取授权信息
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权方法...");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//资源授权码
//info.addStringPermission("productAdd");
//进行通配符授权
info.addStringPermission("product:*");
//角色授权码
info.addRole("admin");
return info;
}
//认证方法:获取认证信息
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证方法...");
//判断用户名是否存在, 判断密码是否正确
//1.如果获取用户输入的账户信息?
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername();
//2.如果获取数据库的账户信息?
//模拟数据库的账户信息
String name = "jack";
String password = "123";
//判断用户名
if(!username.equals(name)){
return null; // shiro 底层自动抛出 UnknownAccountException
}
//判断密码
/**
* 参数一: principal, 用于把数据回传到 login 方法
* 参数二: 数据库的密码
* Shiro 底层对比密码的结果:
* 1) 密码正确: 认证通过
* 2) 密码不正确: 自动抛出 IncorrectCredentialsException
* 参数三: realm 的名称, 只有在多个 realm 的是才会使用
*/
return new SimpleAuthenticationInfo("callback",password,"");
}
}
建立 ini 配置 SecurityManager 关联 Realm
myRealm= com.shiro.realms.MyRealm
securityManager.realm=$myRealm
编写 Shiro 的认证流程
public class Test1 {
public static void main(String[] args) {
//1.创建安全管理器工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2.创建安全管理器
SecurityManager securityManager = factory.getInstance();
//3.初始化 SecurityUtils 工具类
SecurityUtils.setSecurityManager(securityManager);
//4.从 SecurityUtils 工具中获取 Subject
Subject subject = SecurityUtils.getSubject();
//5.认证操作(登录)
//AuthenticationToken: 用于封装用户输入的账户信息
AuthenticationToken token = new UsernamePasswordToken("jack","123");
try {
subject.login(token);
//如果 login 方法没有任何异常, 代表认证成功
//获取SimpleAuthenticationInfo方法的第一个参数principal
Object principal = subject.getPrincipal();
System.out.println("登录成功:"+principal);
} catch (UnknownAccountException e) {
//账户不存在
System.out.println("账户不存在");
} catch (IncorrectCredentialsException e) {
//密码错误
System.out.println("密码错误");
} catch (Exception e) {
//系统错误
System.out.println("系统错误");
}
}
}
Shiro 的授权操作分为两种不同方式:
1) 基于资源的授权
必须得到资源的授权码才可以访问该资源
2) 基于角色的授权
必须得到该角色, 才可以访问该资源
注意: 如果要进行 Shiro 的授权操作, 必须先完成 Shiro 的认证。
subject.login(token);
//如果 login 方法没有任何异常, 代表认证成功
//获取SimpleAuthenticationInfo方法的第一个参数principal
Object principal = subject.getPrincipal();
System.out.println("登录成功:"+principal);
//进行 Shiro 的授权
//1.基于资源的授权
//判断当前登录用户是否有“商品添加”功能
//isPermitted():返回 true,有权限, false: 没有权限
System.out.println("productAdd="+subject.isPermitted("product:add"));
System.out.println("productUpdate="+subject.isPermitted("product:update"));
//2.基于角色的授权
//判断当前登录用户是否为“超级管理员”
System.out.println("admin="+subject.hasRole("admin"));