shiro学习第三天
紧接着上一天的学习,已经在JavaSE环境下简单实现了shiro框架的权限登录认证过程。考虑到将来要从数据库当中读取shiro的验证信息并进行验证,使用JdbcRealm。
既然要从数据数据库进行读取shiro的验证信息,我们就必须需要建立相应的数据库表,在实际开发中用户名密码、角色、权限都需要去进行动态的管理,这里进行了了一个简单的关系建立包括三张表:
用户表:shiro_user
用户角色表:shiro_role_permission
角色 权限表:shiro_role_permission
这三张表通过角色名字进行关联
接下来就需要进行工程的搭建,搭建其实和前一天的过程一样,只是在其pom.xml中添加spring-jdbc的jar包和mysql驱动包,如有需要不懂得可以参考https://blog.csdn.net/liu__jiang/article/details/91452894这篇文章。
1.添加pring-jdbc和mysql的jar包
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
2.编写配置文件,在resources下建立shiro-mysql.ini(名字随意)
[main]
dataSource=org.springframework.jdbc.datasource.DriverManagerDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://127.0.0.1:3306/shirotest
dataSource.username=root
#如果数据库没有密码,就不要写这行
dataSource.password=246810
#配置Realm
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
#是否检查权限
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.dataSource=$dataSource
#重写JdbcRealm中默认的sql语句
#根据用户名查询出密码
jdbcRealm.authenticationQuery = select PASSWORD from SHIRO_USER where USER_NAME = ?
#根据用户名查询出角色
jdbcRealm.userRolesQuery = select ROLE_NAME from SHIRO_USER_ROLE where USER_NAME = ?
#根据角色名查询出权限
jdbcRealm.permissionsQuery = select PERM_NAME from SHIRO_ROLE_PERMISSION WHERE ROLE_NAME = ?
#将数据源指定给securityManager,如有多个,分割直接加即可。
securityManager.realms=$jdbcRealm
3.java代码读取配置文件,进行权限验证判断。
import org.apache.shiro.SecurityUtils;
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;
public class ShiroJdbcTest {
public static void main(String[] args) {
//1.加载shiro的配置文件,返会一个Factory对象,管理SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-mysql.ini");
//2.获得SecurityManager对象
SecurityManager securityManager = factory.getInstance();
//3。将SecurityManager绑定到上下文中,全局绑定,只需一次
SecurityUtils.setSecurityManager(securityManager);
//4.获得与当前系统交互的对象subject
Subject subject = SecurityUtils.getSubject();
//5.进行登录,用用户名和密码进行登录,创建用户名和密码票据
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");
//6.检验账户是否被验证过
// subject.isAuthenticated()
try {
// 7.进行登陆
subject.login(token);
if (subject.isAuthenticated()) {
System.out.println("登陆成功");
//7.判断角色
if(subject.hasRole("admin")){
System.out.println("有admin角色");
}else{
System.out.println("没有admin角色");
}
//7.判断权限
if(subject.isPermitted("/add.html")){
System.out.println("有这个权限");
}else{
System.out.println("没有这个权限");
}
}
} catch (Exception e) {
System.out.println("用户名或密码错误,登陆失败");
}
}
}
我们也可以自定义实现Realm,如果想要自定义实现Realm我们必须继承AuthorizingRealm,它是一个自带验证和缓存功能的Realm可通过查看源码得知(这里不做详细解释,后期再说),具体实现如下:
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.jdbc.core.JdbcTemplate;
public class MyRelam2 extends AuthorizingRealm {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//权限验证调用
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("权限验证");
String sql = "select ROLE_NAME from SHIRO_USER_ROLE where USER_NAME = ?";
String username = (String) principalCollection.getPrimaryPrincipal();
List<String> roles = jdbcTemplate.queryForList(sql, String.class, username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
return info;
}
//登录的时候调用
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("doGetAuthenticationInfo");
String sql = "select PASSWORD from SHIRO_USER where USER_NAME = ?";
String username = (String) authenticationToken.getPrincipal();
//参数1:要查询的sql,参数2:要封装的类型,参数三:查询的条件
String password = jdbcTemplate.queryForObject(sql, String.class, username);
//将查询结果返会给shiro,方便验证
SimpleAuthenticationInfo info =
new SimpleAuthenticationInfo(username, password, null, getName());
return info;
}
}
测试代码:
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.authz.permission.WildcardPermissionResolver;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class ShiroIniTest1 {
public static void main(String[] args) {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
securityManager.setAuthenticator(authenticator);
ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
authorizer.setPermissionResolver(new WildcardPermissionResolver());
securityManager.setAuthorizer(authorizer);
//创建dataSource对象
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//设置数据
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/shirotest");
dataSource.setUsername("root");
dataSource.setPassword("246810");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
MyRelam2 myRealm2 = new MyRelam2();
myRealm2.setJdbcTemplate(jdbcTemplate);
securityManager.setRealm(myRealm2);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("a", "a");
try {
subject.login(token);
System.out.println(subject.hasRole("test"));
System.out.println("登录成功");
} catch (AuthenticationException e) {
//e.printStackTrace();
System.out.println("用户名或密码错误,登录失败");
}
}
}
到此为止,我们已经学习了使用配置文件从数据库读取验证信息和自定义数据源从数据库读取验证信息的方法。接下来,让我们将其整合到web环境中,毕竟实际开发不会在JavaSE环境下使用,这三天只是学习了shiro进行登录信息验证及权限判断的过程是怎样的。