Shiro官方:http://shiro.apache.org
示例代码:https://gitee.com/itwenke/spring-boot-demo/tree/master/shiro
Shiro是一个强大且易于使用的Java安全框架,用于身份验证、授权、加密和会话管理等安全功能。它提供了简单直观的API,使得开发人员能够轻松地集成安全功能到他们的应用程序中。Shiro的设计目标是使安全变得简单,同时提供高度的可定制性和可扩展性,以满足各种复杂的安全需求。
Shiro框架的核心概念包括:
Subject:代表当前用户,可以是一个人、设备或者第三方服务。Subject可以执行身份验证和授权操作。
SecurityManager:负责管理所有的Subject,是Shiro框架的核心。它协调着所有的安全操作,包括身份验证、授权、会话管理等。
Realm:用于验证用户身份和获取用户的授权信息。Realm通常连接到后端的数据源,如数据库、LDAP等。
SessionManager:管理用户的会话,包括创建、删除、过期等操作。
Shiro框架的优点包括简单易用、灵活性高、可定制性强、功能完善等。它可以与各种Java框架和技术无缝集成,如Spring、Servlet容器、JAX-RS等。因此,Shiro框架成为了许多Java应用程序的首选安全解决方案。
具体代码操作:
public class Demo {
@Test
public void authen() {
// 创建 SimpleAccountRealm
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
simpleAccountRealm.addAccount("admin", "admin", "超级管理员", "物流管理员");
// 创建 DefaultSecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// DefaultSecurityManager 与 SimpleAccountRealm 建立连接
securityManager.setRealm(simpleAccountRealm);
// Subject 和 DefaultSecurityManager 建立关系
SecurityUtils.setSecurityManager(securityManager);
// 获取 Subject
Subject subject = SecurityUtils.getSubject();
// 发起认证
subject.login(new UsernamePasswordToken("admin", "admin"));
// 用户名错误,抛出异常:org.apache.shiro.authc.UnknownAccountException
// 密码错误,抛出异常:org.apache.shiro.authc.IncorrectCredentialsException
// 判断是否认证成功
System.out.println("是否认证成功:" + subject.isAuthenticated());
// 校验权限
System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));
System.out.println("是否拥有物流管理员:" + subject.hasRole("物流管理员"));
System.out.println("是否拥有商品管理员:" + subject.hasRole("商品管理员"));
// 退出登录
subject.logout();
System.out.println("是否认证成功:" + subject.isAuthenticated());
}
}
运行结果:
是否认证成功:true
是否拥有超级管理员角色:true
是否拥有物流管理员:true
是否拥有商品管理员:false
是否认证成功:false
具体代码操作:
shiro.ini 配置文件:
[users]
admin=admin,超级管理员,运营管理员,商品管理员
test=123456,商品管理员
[roles]
超级管理员=user:add,user:update,user:delete
商品管理员=perm1,perm2
验证:
public class Demo {
@Test
public void authen() {
// 创建 SimpleAccountRealm
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
// 创建 DefaultSecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// DefaultSecurityManager 与 IniRealm 建立连接
securityManager.setRealm(iniRealm);
// Subject 和 DefaultSecurityManager 建立关系
SecurityUtils.setSecurityManager(securityManager);
// 获取 Subject
Subject subject = SecurityUtils.getSubject();
// 发起认证
subject.login(new UsernamePasswordToken("admin", "admin"));
System.out.println("是否认证通过:" + subject.isAuthenticated());
// 角色校验
System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));
// 权限校验
System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
subject.checkPermission("user:update"); // 没有权限就抛异常:org.apache.shiro.authz.UnauthorizedException
}
}
运行结果:
是否认证通过:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true
具体代码操作:
public class Demo {
@Test
public void authen(){
// 创建 JdbcRealm
JdbcRealm jdbcRealm = new JdbcRealm();
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///shiro-jdbc");
dataSource.setUsername("root");
dataSource.setPassword("root");
jdbcRealm.setDataSource(dataSource);
// 开启权限校验
jdbcRealm.setPermissionsLookupEnabled(true);
// 创建 DefaultSecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// DefaultSecurityManager 与 SimpleAccountRealm 建立连接
securityManager.setRealm(jdbcRealm);
// Subject 和 DefaultSecurityManager 建立关系
SecurityUtils.setSecurityManager(securityManager);
// 获取 Subject
Subject subject = SecurityUtils.getSubject();
// 发起认证
subject.login(new UsernamePasswordToken("admin", "admin"));
// 判断是否认证成功
System.out.println("是否认证成功:" + subject.isAuthenticated());
// 角色校验
System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));
// 权限校验
System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
}
}
运行结果:
是否认证成功:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true
强烈推荐!!!
强烈推荐!!!
强烈推荐!!!
具体代码操作:
声明POJO类,继承AuthorizingRealm
public class CustomRealm extends AuthorizingRealm {
{
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("MD5");
matcher.setHashIterations(1024);
this.setCredentialsMatcher(matcher);
}
/**
* 用户认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取用户名
String username = (String) authenticationToken.getPrincipal();
// 判断用户名(非空)
if(username == null || username.equals("")){
// 返回null,默认抛出一个异常:org.apache.shiro.authc.UnknownAccountException
return null;
}
// 根据用户名查询用户
User user = this.findUserByUsername(username);
// 判断用户是否为null
if(user == null) {
return null;
}
// 声明 SimpleAuthenticationInfo 对象,并填充用户信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),"CustomRealm");
// 设置盐
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
return simpleAuthenticationInfo;
}
/***
* 授权认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取认证用户
User user = (User) principalCollection.getPrimaryPrincipal();
// 根据用户获取当前用户拥有的角色
Set<String> roleSet = this.findRolesByUser(user);
// 根据用户拥有的角色查询权限信息
Set<String> permSet = this.findPermsByRoleSet(roleSet);
// 声明 SimpleAuthorizationInfo 对象,并填充角色信息和权限信息
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
simpleAuthenticationInfo.setRoles(roleSet);
simpleAuthenticationInfo.setStringPermissions(permSet);
return simpleAuthenticationInfo;
}
/**
* 生成加盐的MD5密码
*/
public static void main(String[] args) {
System.out.println(new Md5Hash("admin", "abcdefg123456", 1024));
}
/**
* 模拟数据库操作
*/
private User findUserByUsername(String username) {
if("admin".equals(username)){
User user = new User();
user.setId(1);
user.setUsername("admin");
user.setPassword("3e48d56a6fc20c50f589f562cdf20451");
user.setSalt("abcdefg123456");
return user;
}
return null;
}
/**
* 模拟数据库操作
*/
private Set<String> findRolesByUser(User user) {
Set<String> set = new HashSet<>();
set.add("超级管理员");
set.add("运营管理员");
return set;
}
/**
* 模拟数据库操作
*/
private Set<String> findPermsByRoleSet(Set<String> roleSet) {
Set<String> set = new HashSet<>();
set.add("user:add");
set.add("user:update");
return set;
}
}
用户类:
@Data
public class User {
private Integer id;
private String username;
private String password;
private String salt;
}
验证:
public class Demo {
@Test
public void authen(){
// 创建 JdbcRealm
CustomRealm customRealm = new CustomRealm();
// 创建 DefaultSecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// DefaultSecurityManager 与 SimpleAccountRealm 建立连接
securityManager.setRealm(customRealm);
// Subject 和 DefaultSecurityManager 建立关系
SecurityUtils.setSecurityManager(securityManager);
// 获取 Subject
Subject subject = SecurityUtils.getSubject();
// 发起认证
subject.login(new UsernamePasswordToken("admin", "admin"));
// 判断是否认证成功
System.out.println("是否认证成功:" + subject.isAuthenticated());
// 角色校验
System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));
// 权限校验
System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
}
}
运行结果:
是否认证成功:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true