学习过程中感觉不如 jwt+aop+自定义注解 灵活
但比springsecurity更加小巧,也可脱离Spring框架独立使用
下面是一张官网首页的架构图片
三大功能模块
- Security Manager 安全管理器,管理所有
- Subject Realms 用于进行权限信息的验证,一般需要自己实现
- Subject 主体,一般指用户。
细分功能
- Authentication:身份认证/登录(账号密码验证)。
- Authorization:授权,即角色或者权限验证。
依赖安装
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
先从做个简单的Demo了解一下
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser() {
// 简易版,实际从数据库获取
simpleAccountRealm.addAccount("orange", "123456");
simpleAccountRealm.addAccount("admin", "123456", "vip1");
}
@Test
public void testAuthentication() {
//1,构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2,主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3,登录
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");
subject.login(token);
//4,验证
System.out.println("是否认证登录:"+subject.isAuthenticated());
subject.checkRole("vip1");
}
}
实战:自定义Realm
通过上面的一个Demo相信也明白了流程了吧,接下来要自定义一个Realm,连接数据库去读取密码
public class CustomRealm extends AuthorizingRealm {
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
// 从数据库或者缓存中获取角色数据
Set<String> roles = getRolesByUserName(username);
Set<String> permissions = getPermissionsByUserName(username);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
private Set<String> getPermissionsByUserName(String username) {
Set<String> sets = new HashSet<>();
sets.add("user:delete");
sets.add("user:add");
return sets;
}
private Set<String> getRolesByUserName(String username) {
Set<String> sets = new HashSet<>();
sets.add("vip1");
return sets;
}
/**
* 验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 1,通过主体传过来的认证信息中,获取用户名
String username = (String) authenticationToken.getPrincipal();
// 2,通过用户名到数据库中获取凭证
String password = getPasswordByUserName(username);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo
(username, password, "customRealm");
return authenticationInfo;
}
private String getPasswordByUserName(String username) {
Map<String, String> userMap = new HashMap<>();
userMap.put("orange", "123456");
return userMap.get(username);
}
}
- 使用的是模拟数据库环境
- 需要继承AuthorizingRealm,并且实例化添加到SecurityManager中
public class CustomRealmTest {
@Test
public void testAuthentication() {
CustomRealm customRealm = new CustomRealm();
//1,构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
// SecurityUtils 给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2,主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3,登录
UsernamePasswordToken token = new UsernamePasswordToken("orange", "123456");
subject.login(token);
//4,验证
System.out.println("是否认证登录:"+subject.isAuthenticated());
subject.checkRole("vip1");
subject.checkPermission("user:add");
}
}
完成