Shiro权限管理框架简单入门

Shiro权限管理框架简单入门

shrio是Apache的强大灵活的开源安全框架
(spring官网用shiro做安全管理)

Shiro可以提供:
认证、授权、企业会话管理、安全加密
可以非常方便完成项目的权限管理模块的开发

Shiro和Spring Security的比较

	Apache Shrio	Spring security
	简单、灵活		复杂、笨重
	可以脱离Spring	不可脱离Spring
	权限粒度较粗      权限粒度更细

shiro的结构图
Shiro权限管理框架简单入门_第1张图片
用Shiro做安全认证的时候需要先创建SecurityManager对象

1. SecurityManager是用来提供安全服务的

2. 主体(Subject)提交请求认证到

3. SecurityManager(是通过)

4. Authenticator来进行认证的(它做认证的时候需要调用)
 
5. Realm验证获取认证数据(做最终的认证)

代码演示Shiro是如何做认证的

引入Shrio核心包: Shiro-core(maven官网搜索)

public class Authenticator{
//指定realm
SimpleAccountRealm simpleRealm = new SimpleAccountRealm();
@Before
public void addUser(){
	simpleRealm.addAccount("libai","123456");
}

@Test
public void testAuthenticator(){
//1.构建SecurityManager环境
DefaultSecuirtyManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(simpleRealm);


//2.SecurityUtils设置securityManager环境
SecurityUtils.setSecurity(securityManager);
//3.主体提交认证请求

Subject subject = SecurityUtils.getSubject();
//提交认证
UsernamePassToken token = new UsernamePasswordToken("libai","123456");
//登录
subject.login(token);
//是否认证
System.out.println("==="+subject.isAuthenticated());
//退出登录
subject.logout();
	}
}

Shiro的授权

1.创建SecurityManager

2.主体授权

3.SecurityManager授权
	
4.Authorizer授权

5.Realm获取角色权限数据

代码演示Shiro的授权

public class Authenticator{
	//指定realm
	SimpleAccountRealm simpleRealm = new SimpleAccountRealm();
	@Before
	public void addUser(){
		simpleRealm.addAccount("libai","123456","admin","user");
}

@Test
public void testAuthenticator(){
	//1.构建SecurityManager环境
	DefaultSecuirtyManager securityManager = new DefaultSecurityManager();

	securityManager.setRealm(simpleRealm);
	

	//2.SecurityUtils设置securityManager环境
	SecurityUtils.setSecurity(securityManager);
	//3.主体提交认证请求
	
	Subject subject = SecurityUtils.getSubject();
	//提交认证
	UsernamePassToken token = new UsernamePasswordToken("libai","123456");
	//登录
	subject.login(token);
	//是否认证
	System.out.println("==="+subject.isAuthenticated());
	
	//检查用户是否具备这样的角色  //授权可以看checkRole这个方法的源代码实现
	//subject.checkRole("admin")
	subject.checkRoles("admin","user");
	}
}

Shiro的自定义Realm

内置Realm
IniRealm
JdbcRealm
代码演示内置Realm

IniRealm代码演示

public class IniRealm{
@Test
public void testIniRealm(){

	//创建IniRealm  
	//指定文件路径classpath:user.ini(文件名user.ini)

//user.ini设置内容
[users]
//做认证
Mark=123456
//做授权,管理员拥有删除用户的权限
[roles]
admin=user:delete,user:update

	IniRealm iniRealm = new IniRealm("classpath:user.ini");

	//1.构建SecurityManager环境
	DefaultSecuirtyManager securityManager = new DefaultSecurityManager();
	securityManager.setRealm(iniRealm);


	//2.SecurityUtils设置securityManager环境
	SecurityUtils.setSecurity(securityManager);
	//3.主体提交认证请求
	
	Subject subject = SecurityUtils.getSubject();
	//提交认证
	UsernamePassToken token = new UsernamePasswordToken("libai","123456");
	//登录
	subject.login(token);
	//是否认证
	System.out.println("==="+subject.isAuthenticated());
	//检查是否拥有授权
	subject.checkRole("admin");
	//检查是否拥有删除权限
	subject.checkPermission("user:delete");
	subject.checkPermission("user:update");
	}
}

JdbcRealm代码演示
//因为jdbcRealm需要访问数据库,需要引入pom.xml加入依赖
(mysql-connector-java)和(druid(com.alibaba))

public class JdbcRealm{

DruidDataSource dataSource = new DruidDataSource();
{
	dataSource.setUrl("jdbc:mysql://localhost:3306/test");
	dataSource.setUsername("root");
	dataSource.setPassword("root");
}

@Test
public void testJdbcRealm(){

	//JdbcRealm底层代码有默认的sql查询语句,所以能够查询到用户
	
	
	//创建JdbcRealm
	JdbcRealm jdbcRealm = new JdbcRealm();
	jdbc.setDateSource(dataSource);
	//设置权限的开关默认为false
	jdbc.setPremissionsLookupEnable(true);
	//自定义sql语句
	String sql = "select password from test_user where user_name = ?";
	jdbcRealm.setAuthenticationQuery(sql);
	
	//1.构建SecurityManager环境
	DefaultSecuirtyManager securityManager = new DefaultSecurityManager();
	
	securityManager.setRealm("jdbcRealm");

	//2.SecurityUtils设置securityManager环境
	SecurityUtils.setSecurity(securityManager);
	//3.主体提交认证请求
	
	Subject subject = SecurityUtils.getSubject();
	//提交认证   这个地方根据用户名和密码做校验成功是因为数据库user表有这条数据
	UsernamePassToken token = new UsernamePasswordToken("libai","123456");
	//登录
	subject.login(token);
	//是否认证
	System.out.println("==="+subject.isAuthenticated());
	//检查是否拥有授权  这里的角色也是数据库表里面所拥有的才会成功
	subject.checkRole("admin");
	//检查是否拥有删除权限
	subject.checkPermission("user:delete");
	subject.checkPermission("user:update");
	}
}

自定义Relam(需要继承AuthorizingRealm)
代码演示:

public class CustomRealm extends AuthorizingRealm{
	
	Map userMap = new HashMap<>(16);
	{
	userMap.put("Mark","123456");
	super.setName("customRealm");
	}
	//从数据库和缓存中获取角色数据
	private Set getRolesByUserName(String username){
		Set sets = new HashSet<>();
		sets.add("admin");
		sets.add("user");
		return sets;
	}	
	//从数据库和缓存中获取权限数据
	private Set getPermissionsByUserName(String username){
		Set sets = new HashSet<>();
		sets.add("user:delete");
		sets.add("user:add");
		return sets;
	}
	//授权方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){
	
	String username = (String)principalCollection.getPrimaryPrincipal();
	//从数据库和缓存中获取角色数据
	Set roles = getRolesByUserName(username);
	//从数据库和缓存中获取权限数据
	Set permissions = getPermissionsByUserName(username);
	SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
	simpleAuthorizationInfo.setStringPermissions(permissions);
	simpleAuthorizationInfo.setRoles(roles);
	retrun simpleAuthorizationInfo;
	}
	//认证方法
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
		//1.从主体传过来的认证信息中 获得用户名
		String username = (String) authenticationToken.getPrincipal();
		2.通过用户名得到数据库中获取凭证
		String password = getPasswordByUserName(username);
		if(password==null){
			return null;
		}
		SimpleAuthenticationInfo  authenticationInfo = new SimpleAuthenticationInfo("Mark",password,"customRealm");
		retrun authenticationInfo;
	}

	private String getPasswordByUserName(String username){
		//这里本来应该调用数据库获取密码,这里为了演示方便从Map里获取
		return userMap.get(username);
		}
}

测试类调用自定义realm类
public class testCustomRealm{
@Test
public void testAuthenticator(){
	//1.构建SecurityManager环境
	DefaultSecuirtyManager securityManager = new DefaultSecurityManager();
	CustomRealm customRealm = new CustomRealm();
	securityManager.setRealm(customRealm);
	

	//2.SecurityUtils设置securityManager环境
	SecurityUtils.setSecurity(securityManager);
	//3.主体提交认证请求
	
	Subject subject = SecurityUtils.getSubject();
	//提交认证
	UsernamePassToken token = new UsernamePasswordToken("libai","123456");
	//登录
	subject.login(token);
	//是否认证
	System.out.println("==="+subject.isAuthenticated());
	
	//检查用户是否具备这样的角色  //授权可以看checkRole这个方法的源代码实现
	//subject.checkRole("admin")
	subject.checkRoles("admin","user");
	subject.checkPermissions("user:delete","user:add");
	}
}

##Shiro的加密(密码加密)

HashedCredentialsMatcher工具类的使用

//上面在定义Realm测试类第一步下面添加代码
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();

//设置算法名称 可变
matcher.setHashAlgorithmName("md5");

//设置加密次数 可变  
matcher.setHashIterations(1);

//customRealm设置进来这个工具类
customRealm.setCredentialsMatcher(matcher);

//在自定义的CustomRealm获取密码的时候把该Map里面的密码由明文改为密文,提前在main函数里面用MD5把明文密码加密,加密后的密文放到Map的值里面
Md5Hash md5Hash = new Md5Hash("123456");//md5加密后得到密文

加盐的使用

//1.把改密码进行加盐防止对密码进行破解
由于md5加密密码之后的密文是固定的密文存在被解密的风险,加上盐代表把密文加上随机的字符串,大大降低被破解的风险
本案例给的是固定的盐,实际代码可以给随机的
Md5Hash md5Hash = new Md5Hash("123456","huge");
//2.然后把加盐之后的密码给Map的值
//3.在自定义CustomRealm类方法doGetAuthenticationInfo返回值之前把盐设置进去
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("huge"));

你可能感兴趣的:(Shiro权限管理框架)