本案例测试使用的是shiro1.13.0最新版本测试
1、shiro概述?
Apache Shiro是java的一个安全框架,能够实现:认证、授权、加密、会话管理、与Web集成、缓存等。
认证:本质就是判断你输入的用户名和密码跟数据库的是否相同。
授权:即访问控制,判断和控制谁对指定资源是否有访问权限。
2、shiro认证流程概述
1、当前端用户通过输入框输入用户名和密码的时候,后端获取数据后,会将用户名和密码封装成UsernamepasswordToken对象,并通过Subject.login(token);访问SecurityManager安全管理器。
2、SecurityManager安全管理器会将认证操作交给Authenticator(认证管理器),认证管理器会获取认证策略,如用户名和密码认证或者指纹认证登。
3、Authenticator将身份信息传递给Realm(这个Realm可以是系统自带的,也可以是用户自定义的,但是在实际的项目中肯定都是自定义的Realm)。这个Realm就是用来连接数据库验证数据是否正确的地方。
4、Realm认证后会将认证的结果返回给SecurityManager安全管理器,安全管理器会拿着这份数据与Subject中用户输入的数据比对,相同就验证成功,不同就验证失败。
3、shiro使用快速案例-非数据库版本
3.1、创建Maven工程导入shiro包信息
<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>org.example</groupId><artifactId>shirobasedemo1</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>shirobasedemo1</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-all</artifactId><version>1.13.0</version><type>pom</type></dependency></dependencies>
</project>
3.2、在resources目录中创建shiro.ini配置文件
这个使用使用的是默认的realm,直接从配置文件获取用户名和密码
[users]
shiyilang=123456
shierlang=456789
3.3、创建测试类,测试验证结果
此处使用新版本的测试方式
新版本中直接通过IniRealm去访问和解析ini配置文件
public class Test {public static void main(String[] args) {//创建securityManager安全管理器DefaultSecurityManager securityManager= new DefaultSecurityManager();//创建IniRealmIniRealm iniRealm=new IniRealm("classpath:shiro.ini");//解析shiro.ini文件securityManager.setRealm(iniRealm);//将SecurityManager绑定到当前运行环境中,让系统随时随地可以访问securityManager对象SecurityUtils.setSecurityManager(securityManager);//创建当前的登录主体,此时主体没有经过认证(Subject会给SecurityManager委托各种功能)Subject subject= SecurityUtils.getSubject();//绑定主体登录的身份凭证,即账号和密码UsernamePasswordToken token=new UsernamePasswordToken("shiyilang","123456");//主体登录subject.login(token);//login方法的内部,就回去安全管理器//判断登录是否成功System.out.println("验证是否成功:"+subject.isAuthenticated());//注销操作subject.logout();System.out.println("验证是否成功:"+subject.isAuthenticated());}
}
3.4、测试结果
3.5、上述程序源码下载
https://download.csdn.net/download/tangshiyilang/88677731
4、shiro快速使用案例—创建JdbcRealm
当我们的验证不需要很复杂的时候,系统为了方便用户的使用,直接提供了一个封装好的Realm,我们可以快速的使用数据库的方式验证用户名和密码是否正确。
4.1、JdbcRealm功能概述
JdbcRealm会使用内置的SQL语句,所有必须保证用户表的表名必须为 users, 用户名必须为 username, 密码必须为 password 字段。 users 表不一定只有这两个字段,但必须要保证有这两个字段,如果想加盐加密,还需要有password_salt 字段。
JdbcRealm部分源代码分析
从下面的源代码可以看出,我们创建的表名必须叫users,表字段中必须使用username,password等。需要与源码中的内容相合。
public class JdbcRealm extends AuthorizingRealm {protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";private static final Logger log = LoggerFactory.getLogger(JdbcRealm.class);protected DataSource dataSource;protected String authenticationQuery = "select password from users where username = ?";protected String userRolesQuery = "select role_name from user_roles where username = ?";protected String permissionsQuery = "select permission from roles_permissions where role_name = ?";protected boolean permissionsLookupEnabled = false;protected SaltStyle saltStyle;protected boolean saltIsBase64Encoded;
}
4.2、在MySQL中创建user表
CREATE TABLE `users` (`userid` varchar(30) DEFAULT NULL,`username` varchar(30) DEFAULT NULL,`useraddr` varchar(60) DEFAULT NULL,`userage` varchar(20) DEFAULT NULL,`PASSWORD` varchar(50) DEFAULT NULL,`password_salt` varchar(50) DEFAULT NULL,`STATUS` varchar(5) DEFAULT NULL,`remark` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Data for the table `users` */insert into `users`(`userid`,`username`,`useraddr`,`userage`,`PASSWORD`,`password_salt`,`STATUS`,`remark`) values
('1001','雾林小妖','安徽合肥','30','123456',NULL,'1','有点小帅');
4.3、创建maven工程引入配置信息
核心是
shiro-all:我这里使用的是shiro1.13.0版本
mysql驱动包:我的数据库是mysql5.7版本,你可以使用自己版本对应的包版本。
<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>org.example</groupId><artifactId>shirojdbcrealmdemo1</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>shirojdbcrealmdemo1</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-all</artifactId><version>1.13.0</version><type>pom</type></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.4</version></dependency></dependencies>
</project>
4.4、创建JdbcRealm中数据源配置类
public class DataSourceUtil {public static DataSource getDataSource() throws SQLException {//创建连接池核心工具类ComboPooledDataSource dataSource=new ComboPooledDataSource();//设置连接参数:url,驱动,用户密码,初始连接数,最大连接数dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/shiro?useSSL=false&serverTimezone=UTC");dataSource.setDataSourceName("com.mysql.jdbc.Driver");dataSource.setUser("root");dataSource.setPassword("123456");dataSource.setInitialPoolSize(3);dataSource.setMaxPoolSize(6);dataSource.setMaxIdleTime(1000);return dataSource;}
}
4.5、创建测试类测试JdbcRealm
public class Test {public static void main(String[] args) throws SQLException {//创建securityManager安全管理器DefaultSecurityManager securityManager= new DefaultSecurityManager();//创建JdbcRealmJdbcRealm jdbcRealm=new JdbcRealm();//配置JdbcRealm连接数据库参数jdbcRealm.setDataSource(DataSourceUtil.getDataSource());//将Realm绑定到securityManagersecurityManager.setRealm(jdbcRealm);//将SecurityManager绑定到当前运行环境中SecurityUtils.setSecurityManager(securityManager);//创建当前的登录主体,此时主体没有经过认证(Subject会给SecurityManager委托各种功能)Subject subject= SecurityUtils.getSubject();//绑定主体登录的身份凭证,即账号和密码UsernamePasswordToken token=new UsernamePasswordToken("1001","1001");try{subject.login(token);//判断用户是否登录成功if(subject.isAuthenticated()){System.out.println("用户:"+token.getUsername()+", 登录成功");}}catch (Exception e) {e.printStackTrace();System.out.println("没有此账号");}//退出程序subject.logout();System.out.println("用户是否登录成功:"+subject.isAuthenticated());}
}