使用shiro做安全验证和授权管理

apache shiro    不依赖于spring

Apache Shiro是一个强大而灵活的开源安全框架,它能够干净利落地处理身份认证,授权,企业会话管理和加密。

以下是你可以用 Apache Shiro所做的事情:

1.·  验证用户

2.·  对用户执行访问控制,如:

·    判断用户是否拥有角色admin

    判断用户是否拥有访问的权限

3.·  在任何环境下使用 Session API。例如CS程序。

4.·  可以使用多个用户数据源。例如一个是oracle用户库,另外一个是mysql用户库。

5.·  单点登录(SSO)功能。

6.·  “Remember Me”服务 ,类似购物车的功能,shiro官方建议开启。

Shiro的4大部分——身份验证,授权,会话管理和加密

·  Authentication:身份验证,简称“登录”。

·  Authorization:授权,给用户分配角色或者权限资源

·  Session Management:用户session管理器,可以让CS程序也使用session来控制权限

·  Cryptography:把JDK中复杂的密码加密方式进行封装。

----------------------------------------------------------------------------------------------------------------------------------------------------------

Subject 是与程序进行交互的对象,可以是人也可以是服务或者其他,通常就理解为用户。

所有Subject 实例都必须绑定到一个SecurityManager上。我们与一个 Subject 交互,运行时shiro会自动转化为与 SecurityManager交互的特定 subject的交互。

认证流程

SecurityManager Shiro的核心,初始化时协调各个模块运行。然而,一旦 SecurityManager协调完毕,SecurityManager 会被单独留下,且我们只需要去操作Subject即可,无需操作SecurityManager 。 但是我们得知道,当我们正与一个 Subject 进行交互时,实质上是 SecurityManager在处理 Subject 安全操作。

RealmsShiro中作为应用程序和安全数据之间的“桥梁”或“连接器”。他获取安全数据来判断subject是否能够登录,subject拥有什么权限。他有点类似DAO。在配置realms时,需要至少一个realm。而且Shiro提供了一些常用的 Realms来连接数据源,如LDAP数据源的JndiLdapRealmJDBC数据源的JdbcRealmini文件数据源的IniRealmproperties文件数据源的PropertiesRealm,等等。我们也可以插入自己的 Realm实现来代表自定义的数据源。 像其他组件一样,Realms也是由SecurityManager控制

1. subject          认证的用户
2. securitymanager  安全管理器shiro的核心,协调shiro的各个组件
3. Authenticator    认证器注:Authentication Strategy(org.apache.shiro.authc.pam.AuthenticationStrategy) 如果存在多个realm,则接口AuthenticationStrategy会确定什么样算是登录成功(例如,如果一个Realm成功,而其他的均失败,是否登录成功?)。
4. Authorizer       授权器:决定subject能拥有什么样角色或者权限。
5. SessionManager   会话管理器:创建和管理用户session。通过设置这个管理器,shiro可以在任何环境下使用session
 java web容器管理session
 c/s  管理session
6. SessionDao       对session数据的管理
7. Cachemanager    缓存管理器,可以减少不必要的后台访问。提高应用效率,增加用户体验。
8. Realm    程序与安全数据的桥梁

领域 
保存认证数据的模块

保存认证的业务逻辑

可在授权的业务逻辑 
-- 系统realm
-- 自定义realm【重点】
9. cryptography     加密管理   MD5:Shiroapi大幅度简化java api中繁琐的密码加密。

*.ini 配置文件
-- [users]  用户列表
-- [main]
-- [roles]    

测试:


public class TestShiro {
	@Test
	public void t() {
		/**构建securityManager环境*/
		Factory<SecurityManager> factory =new IniSecurityManagerFactory("classpath:shiro-first.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		try {
			//提交认证
			SecurityUtils.getSubject().login(new UsernamePasswordToken("zhangsan","111111"));
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void t2() {
		/**构建securityManager环境*/
		Factory<SecurityManager> factory =new IniSecurityManagerFactory("classpath:shiro-realm.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		try {
			//提交认证
			SecurityUtils.getSubject().login(new UsernamePasswordToken("zhangsan","111111"));
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void t3() {
		/**构建securityManager环境*/
		Factory<SecurityManager> factory =new IniSecurityManagerFactory("classpath:shiro-realm-md5.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		try {
			//提交认证
			SecurityUtils.getSubject().login(new UsernamePasswordToken("zhangsan","111111"));
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void t4() {
		Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
		SecurityManager securityManager = factory.getInstance();
		//构建SecurityManager环境
		SecurityUtils.setSecurityManager(securityManager);
		//认证的主体
		Subject subject = SecurityUtils.getSubject();
		
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","111111");
		try {
			//提交认证
			subject.login(token);//调用CustomRealm
		} catch (AuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("1 认证的结果:" + subject.isAuthenticated());
		//授权的判断
		boolean result1 = subject.hasRole("role1");
		System.out.println("是否拥有角色: " + result1);
		
		boolean result2 = subject.isPermitted("item:delete");
		System.out.println("是否有权限: " + result2);
	}
	
	
}

spring配置模式:

Jar包名称

版本

核心包shiro-core

1.2.0

Web相关包shiro-web

1.2.0

缓存包shiro-ehcache

1.2.0

spring整合包shiro-spring

1.2.0

Ehcache缓存核心包ehcache-core

2.5.3

Shiro自身日志包slf4j-jdk14

1.6.4


使用maven时,在pom中添加依赖包

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
	<version>1.2.0</version>
</dependency>
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-web</artifactId>
	<version>1.2.0</version>
</dependency>
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-ehcache</artifactId>
	<version>1.2.0</version>
</dependency>
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.2.0</version>
</dependency>
<dependency>
	<groupId>net.sf.ehcache</groupId>
	<artifactId>ehcache-core</artifactId>
	<version>2.5.3</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-jdk14</artifactId>
	<version>1.6.4</version>
</dependency>

自定义realm:继承AuthorizingRealm 类


public class CustomRealm extends AuthorizingRealm {

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		//先获取用户名
		//模拟数据库查询用户的权限和角色
		Set<String> roles = new HashSet<>();
		roles.add("role1");
		
		Set<String> permission = new HashSet<>();
		permission.add("item:create");
		permission.add("item:query");
		
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setRoles(roles);
		info.setStringPermissions(permission);
		return info;
	}


	/*@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userid= (String)token.getPrincipal();
		String userid_db="zhangsan";
		String userpassword_db="f51775f5ed43dc50a7488567bb234541";
		String salt = "aaa";
		if(!userid.equals(userid_db)) {
			return null;
		}
		SimpleAuthenticationInfo info =new SimpleAuthenticationInfo(userid,userpassword_db,ByteSource.Util.bytes(salt),"CustomRealm");
		return info;
	}*/
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//先获取用户输入的帐号
		String userId = (String) token.getPrincipal();
		//以下是模拟登录代码
		String userId_db = "zhangsan"; //表示数据库中的帐号
		String password_db = "111111";
		
		if (!userId.equals(userId_db)) {
			return null;
		}
		
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userId, password_db, "CustomRealm");
		return info;
	}

}

web.xml中配置shiro的过滤器:

<!-- Shiro filter-->  
<filter> 
	<filter-name>shiroFilter</filter-name> 
	<filter-class> 
		org.springframework.web.filter.DelegatingFilterProxy  
	</filter-class>  
</filter>  
<filter-mapping>  
	<filter-name>shiroFilter</filter-name>  
	<url-pattern>/*</url-pattern>  
</filter-mapping>  

认证失败:
  -- 帐号错误:org.apache.shiro.authc.UnknownAccountException
  -- 密码错误:org.apache.shiro.authc.IncorrectCredentialsException

自定义Realm


MD5 不可逆   "穷举法"

login.jsp  (login.action) ---> FormAuthenticationFilter(authc)做用户认证
                 ---> 获取username和password
                ----> 调用Realm做认证
--------------------------------------------------------------------------------------------
select* from sys_permission 
where type = 'permission'
and id in 
(select sys_permission_id from sys_role_permission where sys_role_id in (
select sys_role_id from sys_user_role where sys_user_id ='zhangsan'
)

使用shiro做安全验证和授权管理:中医药集中采集系统

猜你喜欢

转载自blog.csdn.net/sinat_41897556/article/details/83960477