Apache Shiro是java的一个安全框架,能够实现:认证、授权、加密、会话管理、与Web集成、缓存等。
认证:本质就是判断你输入的用户名和密码跟数据库的是否相同。
授权:即访问控制,判断和控制谁对指定资源是否有访问权限。
1、当前端用户通过输入框输入用户名和密码的时候,后端获取数据后,会将用户名和密码封装成UsernamepasswordToken对象,并通过Subject.login(token);访问SecurityManager安全管理器。
2、SecurityManager安全管理器会将认证操作交给Authenticator(认证管理器),认证管理器会获取认证策略,如用户名和密码认证或者指纹认证登。
3、Authenticator将身份信息传递给Realm(这个Realm可以是系统自带的,也可以是用户自定义的,但是在实际的项目中肯定都是自定义的Realm)。这个Realm就是用来连接数据库验证数据是否正确的地方。
4、Realm认证后会将认证的结果返回给SecurityManager安全管理器,安全管理器会拿着这份数据与Subject中用户输入的数据比对,相同就验证成功,不同就验证失败。
<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>
这个使用使用的是默认的realm,直接从配置文件获取用户名和密码
[users]
shiyilang=123456
shierlang=456789
此处使用新版本的测试方式
新版本中直接通过IniRealm去访问和解析ini配置文件
public class Test {
public static void main(String[] args) {
//创建securityManager安全管理器
DefaultSecurityManager securityManager= new DefaultSecurityManager();
//创建IniRealm
IniRealm 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());
}
}
https://download.csdn.net/download/tangshiyilang/88677731
当我们的验证不需要很复杂的时候,系统为了方便用户的使用,直接提供了一个封装好的Realm,我们可以快速的使用数据库的方式验证用户名和密码是否正确。
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;
}
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','有点小帅');
核心是
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>
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;
}
}
public class Test {
public static void main(String[] args) throws SQLException {
//创建securityManager安全管理器
DefaultSecurityManager securityManager= new DefaultSecurityManager();
//创建JdbcRealm
JdbcRealm jdbcRealm=new JdbcRealm();
//配置JdbcRealm连接数据库参数
jdbcRealm.setDataSource(DataSourceUtil.getDataSource());
//将Realm绑定到securityManager
securityManager.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());
}
}