Shiro集成SpringMVC工程整合
来源:互联网 发布:java class.getname 编辑:程序博客网 时间:2024/06/06 06:43
Apache Shiro Framework 介绍
第一章:Shiro简介
1、1 Shiro框架简介
Apache Shiro是Java的一个安全框架,旨在简化身份验证和授权。Shiro在JavaSE和JavaEE项目中都可以使用。它主要用来处理身份认证,授权,企业会话管理和加密等。
官网地址如下:http://shiro.apache.org/
Shiro的具体功能点如下:![屏幕快照 2017-08-25 下午4.24.25](屏幕快照 2017-08-25 下午4.24.25.png)
(1)身份认证/登录,验证用户是不是拥有相应的身份;
(2)授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
(3)会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
(4)加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
(5)Web支持,可以非常容易的集成到Web环境;(6) Caching :缓存,存储用户登录之后的信息,拥有角色和权限不需要每次都去查
##### 1、2 Shiro主要有四个组件
SecurityManager典型的 Facade,Shiro 通过它对外提供安全管理的各种服务。
Authenticator对“Who are you ?”进行核实。通常涉及用户名和密码。这 个组件负责收集 principals 和 credentials,并将它们提交给应用系统。如果提交的 credentials 跟应用系统中提供的 credentials 吻合,就能够继续访问,否则需要重新提交 principals 和 credentials,或者直接终止访问。
Authorizer身 份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、用户组、角色和 permission 的聚合体。
Session Manager这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户端或者协议绑定。
同样的虚线框框圈着的是Shiro3大核心组件:
Subject :正与系统进行交互的人,或某一个第三方服务。所有 Subject 实例都被绑定到(且这是必须的)一个SecurityManager 上。
SecurityManager:Shiro 架构的心脏,用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当 Shiro 与一个 Subject 进行交互时,实质上是幕后的 SecurityManager 处理所有繁重的 Subject 安全操作。
Realms :本质上是一个特定安全的 DAO。当配置 Shiro 时,必须指定至少一个 Realm 用来进行身份验证和/或授权。Shiro 提供了多种可用的 Realms 来获取安全相关的数据。如关系数据库(JDBC),INI 及属性文件等。可以定义自己 Realm 实现来代表自定义的数据源。
第二章:Shiro之编码加密
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sudojava.shiro</groupId> <artifactId>shiro_java</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.6.1</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies></project>
2.1、关于shiro加密的说明
Shiro提供了base64和16进制字符串编码/解码的API支持,方便一些编码解码操作。Shiro内部的一些数据的存储/表示都使用了base64和16进制字符串,实现不同的加密算法如下:
产生随机的“盐值”算法
package com.sudojava.shiro.commons;import org.apache.shiro.SecurityUtils;import org.apache.shiro.crypto.RandomNumberGenerator;import org.apache.shiro.crypto.SecureRandomNumberGenerator;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.ByteSource;public class RandomNumberUtils { //随机数的代码生成器 private static RandomNumberGenerator generator; static { generator = new SecureRandomNumberGenerator(); } /** * 获取工具类 * @return */ public static ByteSource getByteSource(){ if (generator!=null){ return generator.nextBytes(); } return null; }}
各种不同的加密算法如下:
package com.sudojava.shiro.cryptography;import com.sudojava.shiro.commons.RandomNumberUtils;import org.apache.shiro.crypto.hash.*;public class CryptoUtils { protected static Object getSalt() { return RandomNumberUtils.getByteSource().toHex(); } public static String cryptoObject(String source,String algorithm,int hashIterations) { switch (algorithm) { case "md5": { Md5Hash md5Hash = new Md5Hash(source,getSalt(),hashIterations); return md5Hash.toHex(); } case "md2": { Md2Hash md2Hash = new Md2Hash(source,getSalt(),hashIterations); return md2Hash.toHex(); } case "sha1": { Sha1Hash sha1Hash = new Sha1Hash(source,getSalt(),hashIterations); return sha1Hash.toHex(); } case "sha256": { Sha256Hash sha256Hash = new Sha256Hash(source,getSalt(),hashIterations); return sha256Hash.toHex(); } default: return null; } }}
测试加密算法结果:
package com.sudojava.shiro.test;import com.sudojava.shiro.cryptography.CryptoUtils;import org.apache.shiro.crypto.hash.Md5Hash;import org.junit.Test;public class TestSimpleHash { @Test public void testMethod() { String username = "admin"; String result1 = CryptoUtils.cryptoObject(username, "md5", 4); System.out.println(result1); String result2 = CryptoUtils.cryptoObject(username, "md2", 4); System.out.println(result2); String result3 = CryptoUtils.cryptoObject(username, "sha1", 4); System.out.println(result3); }}
第三章:Shiro身份认证
用户身份验证,在应用程序中做身份以及角色的认证。一般都是使用用户名和密码作为认证的凭据。
在shiro中,用户需要提供principals (身份)和credentials(证明)给shiro,从而应用能验证用户身份:
principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。
credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
最常见的principals和credentials组合就是用户名/密码了。
第一步:
配置shiro.ini文件,采用硬编码的方式提供认证信息
# =============================================================================# Tutorial INI configuration## Usernames/passwords are based on the classic Mel Brooks' film "Spaceballs" :)# =============================================================================# -----------------------------------------------------------------------------# Users and their (optional) assigned roles# username = password, role1, role2, ..., roleN# -----------------------------------------------------------------------------[users]root = secret, adminguest = guest, guestpresidentskroob = 12345, presidentdarkhelmet = ludicrousspeed, darklord, schwartzlonestarr = vespa, goodguy, schwartz
配置规则:
用户名 = 密码,角色1,角色2,角色3等
模拟用户登录情景
用户登录类:Authorization
package com.sudojava.shiro.authorization;import com.sudojava.shiro.domain.User;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class Authorization { private static final transient Logger log = LoggerFactory.getLogger(Authorization.class); private Factory<SecurityManager> factory; private SecurityManager manager; public Authorization(String shiro_ini) { //获取SecurityManager工厂,加载shiro.ini文件 factory = new IniSecurityManagerFactory(shiro_ini); //得到SecurityManager实例,并绑定给SecurityUtils manager = factory.getInstance(); } /** * 模拟用户登录过程 * * @param user * @return */ public boolean login(User user) { boolean flag = false; SecurityUtils.setSecurityManager(manager); //得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); token.setRememberMe(true);//记住用户登录信息 try { currentUser.login(token);//执行登录操作,进行身份验证 flag = true; } catch (UnknownAccountException e) { log.info("未知用户账号异常"); } catch (IncorrectCredentialsException e) { log.info("凭证不正确"); } catch (ExcessiveAttemptsException e) { log.info("尝试认证次数多于系统指定次数"); } catch (AuthenticationException e) { //所有认证异常的父类 log.info("其他未知错误!"); } } currentUser.logout();//用户登出操作 return flag; }}
测试用户登录结果:
package com.sudojava.shiro.authorization;import com.sudojava.shiro.domain.User;import org.junit.Before;import org.junit.Test;public class TestAuthorization { private Authorization authorization; @Before public void init(){ authorization = new Authorization("classpath:shiro.ini"); } @Test public void login(){ User user = new User(); user.setPassword("guest"); user.setUsername("guest"); boolean flag = authorization.login(user); if (flag){ System.out.println("登录成功"); }else{ System.out.println("登录失败"); } }}
第四章:Shiro 授权机制
在shiro中规定了授权的基本对象包括:Subject、Role和Permission和访问资源等四个主体对象。
Subject:主体
主体,指的是访问应用的用户,一般通知User对象。
Resource:资源
通常是指工程下资源模块,也可以指定特定的业务。
Role:角色
角色代表主体的身份特征,一般一种角色下可以拥有多种主体,所以是一对多的关系,例如:超级管理员、经理、CTO等。
Permission:权限
即指定授予主体操作某一些资源的权力,比如,查看、删除和修改的权力等。
授权方式
Shiro授权方式分为三种:
1、Java代码实现
通过Subject对象实现
2、注解实现
通过@RequireXXX实现
3、在web页面上实现
通过实现
案例讲解
模拟用户登录之后,判断该用户是否拥有一定权限,如果该用户有指定的权限,那么可以执行删除或者修改功能
配置shiro.ini文件
# =============================================================================# Tutorial INI configuration## Usernames/passwords are based on the classic Mel Brooks' film "Spaceballs" :)# =============================================================================# -----------------------------------------------------------------------------# Users and their (optional) assigned roles# username = password, role1, role2, ..., roleN# -----------------------------------------------------------------------------[users]root = secret, adminguest = guest, guestpresidentskroob = 12345, presidentdarkhelmet = ludicrousspeed, darklord, schwartzlonestarr = vespa, goodguy, schwartzjack = 123456,admin# -----------------------------------------------------------------------------# Roles with assigned permissions# roleName = perm1, perm2, ..., permN# -----------------------------------------------------------------------------[roles]admin = user:create,user:update,user:deleteschwartz = lightsaber:*goodguy = winnebago:drive:eagle5
核心BasicRole类:
我们声明一个抽象类,指定登录方法为抽象的方法
package com.sudojava.shiro.role;import com.sudojava.shiro.authorization.Authorization;import com.sudojava.shiro.domain.User;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public abstract class BasicRole<T> { private Factory<SecurityManager> factory; private SecurityManager manager; public BasicRole(String shiro_ini) { //获取SecurityManager工厂,加载shiro.ini文件 factory = new IniSecurityManagerFactory(shiro_ini); //得到SecurityManager实例,并绑定给SecurityUtils manager = factory.getInstance(); } public Factory<SecurityManager> getFactory() { return factory; } public void setFactory(Factory<SecurityManager> factory) { this.factory = factory; } public SecurityManager getManager() { return manager; } public void setManager(SecurityManager manager) { this.manager = manager; } public abstract boolean login(T t);}
核心登录LoginRole类
package com.sudojava.shiro.role;import com.sudojava.shiro.authorization.Authorization;import com.sudojava.shiro.domain.User;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class LoginRole extends BasicRole<User> { private static final transient Logger log = LoggerFactory.getLogger(Authorization.class); public LoginRole(String shiro_ini) { super(shiro_ini); } @Override public boolean login(User user) { SecurityUtils.setSecurityManager(getManager()); Subject subject = SecurityUtils.getSubject(); if (!subject.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); token.setRememberMe(true); try { subject.login(token); if (subject.hasRole("admin")) { log.info("该用户拥有admin角色身份"); if (subject.isPermitted("user:delete")) { log.info("该用户具有删除选项功能"); subject.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); log.info("执行删除操作"); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } return true; } catch (UnknownAccountException e) { log.info("未知用户"); } } return false; }}
核心测试类
package com.sudojava.shiro.role;import com.sudojava.shiro.domain.User;import org.junit.Before;import org.junit.Test;public class TestRole { private LoginRole loginRole; @Before public void init(){ loginRole = new LoginRole("classpath:shiro.ini"); } @Test public void test(){ User user = new User(); user.setUsername("root"); user.setPassword("secret"); boolean flag = loginRole.login(user); System.out.println(flag); }}
关于Shiro.ini配置文件的说明
~~~ini
—————————————————————————–
Users and their (optional) assigned roles
username = password, role1, role2, …, roleN
—————————————————————————–
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz
jack = 123456,admin
~~~
配置shiro.ini用户如下规则:
[users]是标志用户信息,规则如下:
用户名 = 密码,角色1,角色2,角色3……
分析数据结构:一个用户可以拥有多个角色
~~~ini
—————————————————————————–
Roles with assigned permissions
roleName = perm1, perm2, …, permN
—————————————————————————–
[roles]
admin = user:create,user:update,user:delete
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
~~~
[roles] 是标志用户角色拥有什么权限,规则如下:
资源:用户操作
例如:
admin = user:view
admin 拥有user的查看权限
admin = user:create,user:update,user:delete
admin 拥有user的创建和修改、删除权限
admin =user:*
admin 拥有user下的所有权限
admin = system:user :create, delete,view,find
admin 拥有system:user 下的CRUD功能
第五章:Shiro Realm认证流程
在Shiro中Realm(域)可以访问特定的应用程序安全实体(如:用户、角色和权限)以确定身份验证和授权操作。
Realm通常和数据源有关系,例如关系型数据库、文件系统等,具有一对一的对应关系。Realm接口实现使用特定
数据源的API接口访问数据,也就是我们可以在数据库中直接定义 用户表 、 角色表和权限表等,我们可以使用JDBC、Hibernate、JPA的规范访问,Realm本质上是数据访问层的DAO。
由于每个应用程序不同,用户和角色等安全数据可以以多种方式进行表示。 Shiro尝试尽可能保持非侵入性的开发哲学 - 它不要求您实现或扩展任何用户,组或角色接口或类
大多数用户不会直接实现Realm接口,而是扩展其中一个子类AuthenticatingRealm或AuthorizingRealm,大大降低了从头开始实现Realm的工作量。
AuthenticatingRealm类的介绍
该类主要是实现了验证模块的信息,通过它可以实现一系列用户登录校验和角色判断等功能,通常该类是配合CacheManager一起使用的,后面我们在详细介绍。
代码示例
第一步配置shiro_realm.ini文件
[main]#声明一个realmmyRealm1 = com.sudojava.shiro.realm.LoginRealm#指定securityManager的realms实现securityManager.realms=$myRealm1
第二步继承AuthenticatingRealm类
package com.sudojava.shiro.realm;import org.apache.shiro.authc.*;import org.apache.shiro.realm.AuthenticatingRealm;/** * 可以使用Realm获取数据库的基本信息, * 包括User表、权限表、和角色表 */public class LoginRealm extends AuthenticatingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //取出用户名和密码 String username = token.getPrincipal().toString(); String password = new String((char[]) token.getCredentials()); if(!"zhang".equals(username)) { throw new UnknownAccountException(); //如果用户名错误 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //如果密码错误 } return new SimpleAuthenticationInfo(username,password,getName()); }}
备注:采用硬编码的方式,模拟数据库的账号为:zhang 密码为:123
第三步Login类的实现
package com.sudojava.shiro.realm;import com.sudojava.shiro.authorization.Authorization;import com.sudojava.shiro.domain.User;import com.sudojava.shiro.role.BasicRole;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class Login extends BasicRole<User> { private static final Logger log = LoggerFactory.getLogger(Authorization.class); public Login(String shiro_ini) { super(shiro_ini); } @Override public boolean login(User user) { SecurityUtils.setSecurityManager(getManager()); Subject subject = SecurityUtils.getSubject(); if (!subject.isAuthenticated()){ UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword()); token.setRememberMe(true); try { subject.login(token); return true; }catch (UnknownAccountException e){ log.info("账号不匹配"); } } return false; }}
第四步测试类的实现
package com.sudojava.shiro.realm;import com.sudojava.shiro.domain.User;import org.junit.Before;import org.junit.Test;public class TestRealm { private Login login; @Before public void init(){ login = new Login("classpath:shiro_realm.ini"); } @Test public void login(){ User user = new User(); user.setUsername("zhang"); user.setPassword("123"); boolean flag = login.login(user); System.out.println(flag); }}
第六章:Shiro 使用JdbcRealm进行验证
我们先来看看Shiro的认证流程
从上面的继承关系图,我们可以看出来一般都是继承AuthorizingRealm就可以了,自带缓存的功能。
Shiro Realm主要默认实现:
org.apache.shiro.realm.text.IniRealm:
通过ini文件配置进行验证, [users]部分指定用户名/密码及其角色;
[roles]部分指定角色即权限信息;
org.apache.shiro.realm.text.PropertiesRealm:
user.username=password,role1,role2 标志用户名密码和角色
role.role1=permission1,permission2 标志角色和权限信息org.apache.shiro.realm.jdbc.JdbcRealm:
我们可以通过创建对应的表,使用sql语句查询出来对应的信息:
获取用户密码:“select“select password from users where username = ?”,
获取用户密码及盐:“select password, password_salt from users where username = ?”
获取用户角色:“select role_name from user_roles where username = ?”
获取角色对应的权限信息:“select permission from roles_permissions where role_name = ?”
也可以调用相应的api进行自定义sql。
使用JdbcRealm进行验证示例步骤:
第一步:创建shiro-jdbc-realm.ini文件
[main]# 配置JDBC数据库连接dataSource=com.alibaba.druid.pool.DruidDataSourcedataSource.driverClassName=com.mysql.jdbc.DriverdataSource.url=jdbc:mysql://localhost:3306/shirodataSource.username=rootdataSource.password=root# JdbcRealmjdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm# 允许授权查询jdbcRealm.permissionsLookupEnabled = truejdbcRealm.dataSource=$dataSource#编写查询数据库的SQL语句jdbcRealm.authenticationQuery = select password from users where username = ?jdbcRealm.userRolesQuery = select a.role_name from user_roles a,users b where a.users_id = b.id and b.username = ?jdbcRealm.permissionsQuery =select a.permission FROM roles_permissions a,user_roles b where b.role_id = a.user_roles_role_id and b.role_name = ?securityManager.realms=$jdbcRealm
第二步:在pom.xml文件中添加DataSource,使用的是阿里巴巴的数据驱动
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.0</version></dependency><!-- 添加mysql数据驱动 --><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version></dependency>
第三步:创建用户表users、user_roles、roles_permissions表
~~~mysql
CREATE TABLE IF NOT EXISTS shiro
.users
(
id
INT NOT NULL,
username
VARCHAR(100) NULL,
password
VARCHAR(100) NULL,
password_salt
VARCHAR(100) NULL,
PRIMARY KEY (id
))
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS shiro
.user_roles
(
role_id
INT NOT NULL,
role_name
VARCHAR(100) NULL,
users_id
INT NOT NULL,
PRIMARY KEY (role_id
),
INDEX fk_user_roles_users1_idx
(users_id
ASC),
CONSTRAINT fk_user_roles_users1
FOREIGN KEY (users_id
)
REFERENCES shiro
.users
(id
)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS shiro
.roles_permissions
(
permission
VARCHAR(100) NULL,
p_id
INT NOT NULL,
user_roles_role_id
INT NOT NULL,
PRIMARY KEY (p_id
),
INDEX fk_roles_permissions_user_roles1_idx
(user_roles_role_id
ASC),
CONSTRAINT fk_roles_permissions_user_roles1
FOREIGN KEY (user_roles_role_id
)
REFERENCES shiro
.user_roles
(role_id
)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
~~~
备注:请校验数据库的名称。
第四步:创建JDBCRealm相关的类
package com.sudojava.shiro.jdbcrealm;import com.sudojava.shiro.authorization.Authorization;import com.sudojava.shiro.domain.User;import com.sudojava.shiro.basic.BasicShiro;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.Permission;import org.apache.shiro.authz.permission.WildcardPermission;import org.apache.shiro.subject.Subject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class LoginForJdbcRealm extends BasicShiro<User> { private static final Logger log = LoggerFactory.getLogger(Authorization.class); public LoginForJdbcRealm(String shiro_ini) { super(shiro_ini); } @Override public boolean login(User user) { SecurityUtils.setSecurityManager(getManager()); Subject subject = SecurityUtils.getSubject(); if (!subject.isAuthenticated()){ UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword()); try { subject.login(token); token.setRememberMe(true); if (subject.hasRole("manager")){ log.info("该用户拥有 manager 角色"); subject.checkPermission("delete"); if (subject.isPermitted("delete")){ log.info("该用户具有删除的权限"); subject.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); log.info("删除资源中......"); } catch (Exception e) { e.printStackTrace(); } } }); } } return true; } catch (UnknownAccountException e) { log.info(e.getMessage()+"账号名有误"); } } return false; }}
模拟用户登录操作
package com.sudojava.shiro.jdbc;import com.sudojava.shiro.domain.User;import com.sudojava.shiro.jdbcrealm.LoginForJdbcRealm;import org.junit.Before;import org.junit.Test;public class TestForJdbc { private LoginForJdbcRealm realm; @Before public void setup(){ realm = new LoginForJdbcRealm("classpath:shiro-jdbc-realm.ini"); } @Test public void login(){ User user = new User(); user.setPassword("123"); user.setUsername("admin"); boolean flag = realm.login(user); System.out.println(flag); }}
第七章:使用原生的Java代码对Realm类进行校验和授权操作
在shiro中我们可以采用Java代码对JdbcRealm进行封装,直接在登录模块进行校验操作。
手动封装Java类
package com.sudojava.shiro.nativeRealm;import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.realm.jdbc.JdbcRealm;public class RealmDataSource { private MysqlDataSource dataSource; private DefaultSecurityManager securityManager; private JdbcRealm jdbcRealm; public RealmDataSource() { try { dataSource = new MysqlDataSource(); dataSource.setUser("root"); dataSource.setPassword("root"); dataSource.setServerName("localhost"); dataSource.setLoginTimeout(2); dataSource.setUrl("jdbc:mysql://localhost:3306/shiro"); jdbcRealm = new JdbcRealm(); jdbcRealm.setDataSource(dataSource); jdbcRealm.setPermissionsLookupEnabled(true); //验证 String authentication_sql = "select password from users where username = ?"; jdbcRealm.setAuthenticationQuery(authentication_sql); //验证角色 String user_roles_sql = "select a.role_name from user_roles a,users b where a.users_id = b.id and b.username = ?"; jdbcRealm.setUserRolesQuery(user_roles_sql); String permission_sql = "select a.permission FROM roles_permissions a,user_roles b where b.role_id = a.user_roles_role_id and b.role_name = ?"; jdbcRealm.setPermissionsQuery(permission_sql); securityManager = new DefaultSecurityManager(jdbcRealm); } catch (Exception e) { e.printStackTrace(); } } public DefaultSecurityManager getSecurityManager() { return securityManager; } /** * @return */ public MysqlDataSource getDataSource() { if (dataSource != null) { return dataSource; } return null; }}
模拟用户登录操作
package com.sudojava.shiro.nativeRealm;import com.sudojava.shiro.authorization.Authorization;import com.sudojava.shiro.domain.User;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class NativeLogin { private static final Logger log = LoggerFactory.getLogger(Authorization.class); private RealmDataSource dataSource; public NativeLogin() { dataSource = new RealmDataSource(); } public boolean login(User user) { boolean flag = false; SecurityUtils.setSecurityManager(dataSource.getSecurityManager()); Subject subject = SecurityUtils.getSubject(); if (!subject.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); token.setRememberMe(true); try { subject.login(token); System.out.println("login successfully"); flag = true; if (subject.hasRole("manager")){ log.info("该用户拥有 manager 角色"); subject.checkPermission("delete"); if (subject.isPermitted("delete")){ log.info("该用户具有删除的权限"); subject.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); log.info("删除资源中......"); } catch (Exception e) { e.printStackTrace(); } } }); } } } catch (UnknownAccountException e) { e.printStackTrace(); } } return flag; }}
测试Java类
package com.sudojava.shiro.nativerealm;import com.sudojava.shiro.domain.User;import com.sudojava.shiro.nativeRealm.NativeLogin;import org.junit.Before;import org.junit.Test;public class TestNative { private NativeLogin nativeLogin; @Before public void setup(){ nativeLogin = new NativeLogin(); } @Test public void loginUser(){ User user = new User(); user.setPassword("123"); user.setUsername("admin"); boolean flag = nativeLogin.login(user); System.out.println(flag); }}
第八章:Shiro Web整合以及实现等验证操作
Shiro提供了与Web集成环境的安全应用支持,
我们在Web工程下的web.xml配置简单的ShiroFilter来控制所有的URL请求,并且根据请求进行转发,
其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前端控制器,其是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。
- Shiro集成SpringMVC工程整合
- Shiro集成SpringMVC工程整合
- SpringMVC+Apache Shiro集成
- springMVC与shiro集成
- Springmvc集成Shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- SpringMVC整合shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- springmvc整合shiro
- SpringMVC整合Shiro
- SpringMVC整合Shiro
- Springmvc整合shiro
- SpringMVC整合Shiro
- socket--udp编程
- python导入caffe模块的问题
- js获取元素样式
- Python模拟登陆知乎,获取收藏夹内容
- 4. Median of Two Sorted Arrays
- Shiro集成SpringMVC工程整合
- 爆发~大数据时代预见未来的新思维
- 基于Dragonboard 410c的智能开关
- IntelliJ IDEA的Rebuild顺序,运行的文件跟原文件不相同
- Twitter 架构优化之路--Twitter是如何做到每秒处理3000张图片
- Codeforces 842C(思维)
- 微信小程序入门
- 洛谷P3074牛奶调度解题报告
- [初学笔记] 转义字符 转换字符 escape characters