打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
shiro框架学习-4- Shiro内置JdbcRealm

1.  JdbcRealm 数据库准备

JdbcRealm就是用户的角色,权限都从数据库中读取,也就是用来进行用户认证授权的安全数据源更换为从数据库中读取,其他没有差别,首先在数据库创建三张表:

CREATE TABLE `users` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `username` varchar(100) DEFAULT NULL,  `password` varchar(100) DEFAULT NULL,  `password_salt` varchar(100) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `idx_users_username` (`username`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `user_roles` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `username` varchar(100) DEFAULT NULL,  `role_name` varchar(100) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `idx_user_roles` (`username`,`role_name`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `roles_permissions` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `role_name` varchar(100) DEFAULT NULL,  `permission` varchar(100) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `idx_roles_permissions` (`role_name`,`permission`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `users` VALUES (1,'jack','123',NULL),(2,'xdclass','456',NULL);INSERT INTO `roles_permissions` VALUES (4,'admin','video:*'),(3,'role1','video:buy'),(2,'role1','video:find'),(5,'role2','*'),(1,'root','*');INSERT INTO `user_roles` VALUES (1,'jack','role1'),(2,'jack','role2'),(4,'xdclass','admin'),(3,'xdclass','root');

2. JdbcRealm 配置文件

#注意 文件格式必须为ini,编码为ANSI#声明Realm,指定realm类型jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm#配置数据源#dataSource=com.mchange.v2.c3p0.ComboPooledDataSourcedataSource=com.alibaba.druid.pool.DruidDataSource# mysql-connector-java 5 用的驱动url是com.mysql.jdbc.Driver,mysql-connector-java6以后用的是com.mysql.cj.jdbc.DriverdataSource.driverClassName=com.mysql.cj.jdbc.Driver#避免安全警告dataSource.url=jdbc:mysql://localhost:3306/xdclass_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falsedataSource.username=rootdataSource.password=lchadmin#指定数据源jdbcRealm.dataSource=$dataSource#开启查找权限,否则不会自动查询角色对应的权限,造成实际有权限,调用subject.isPermitted()返回falsejdbcRealm.permissionsLookupEnabled=true#指定SecurityManager的Realms实现,设置realms,可以有多个,用逗号隔开securityManager.realms=$jdbcRealm

 

测试代码

package net.xdclass.xdclassshiro;import com.alibaba.druid.pool.DruidDataSource;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.realm.jdbc.JdbcRealm;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.junit.Test;/** * jdbcRealm操作 */public class QuicksStratTest5_3 {    @Test    public void testAuthentication() {        //通过配置文件创建SecurityManager工厂        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:jdbcrealm.ini");       // 获取SecurityManager实例        SecurityManager securityManager = factory.getInstance();        //设置当前上下文        SecurityUtils.setSecurityManager(securityManager);        //获取当前subject(application应用的user)        Subject subject = SecurityUtils.getSubject();        // 模拟用户输入        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack","123");        //        subject.login(usernamePasswordToken);        System.out.println("认证结果(是否已授权):"   subject.isAuthenticated());        //最终调用的是org.apache.shiro.authz.ModularRealmAuthorizer.hasRole方法        System.out.println("是否有role1角色:"   subject.hasRole("role1"));        System.out.println("是否有role2角色:"   subject.hasRole("role2"));        System.out.println("是否有root角色:"   subject.hasRole("root"));        //获取登录 账号        System.out.println("getPrincipal():"   subject.getPrincipal());        //校验角色,没有返回值,校验不通过,直接跑出异常        subject.checkRole("role1");        System.out.println("=======subject.checkRole(\"role1\") passed=====" );        // user jack有video的find权限,执行通过        subject.checkPermission("video:find");        // 是否有video:find权限:true        System.out.println("是否有video:find权限:"   subject.isPermitted("video:find"));        //   是否有video:delete权限:false        System.out.println("是否有video:delete权限:"   subject.isPermitted("video:delete"));        //user jack没有video的删除权限,执行会报错:org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [video:delete]        subject.checkPermission("video:delete");        subject.logout();        System.out.println("logout后认证结果:"   subject.isAuthenticated());       /* org.apache.shiro.realm.jdbc.JdbcRealm源码       * 1. class JdbcRealm extends AuthorizingRealm       * 2. 预置了默认的查询语句,因此创建数据库时字段名字要与这里定义的一致!!!       *   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 = ?";    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 = ?";    *    * 3. protected boolean permissionsLookupEnabled = false;  这个开关默认是关闭的,需要手动打开    * 4.    * protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        if (principals == null) {            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");        } else {            String username = (String)this.getAvailablePrincipal(principals);            Connection conn = null;            Set<String> roleNames = null;            Set permissions = null;            try {                conn = this.dataSource.getConnection();                roleNames = this.getRoleNamesForUser(conn, username);                if (this.permissionsLookupEnabled) {                    permissions = this.getPermissions(conn, username, roleNames);                }            } catch (SQLException var11) {                String message = "There was a SQL error while authorizing user ["   username   "]";                if (log.isErrorEnabled()) {                    log.error(message, var11);                }                throw new AuthorizationException(message, var11);            } finally {                JdbcUtils.closeConnection(conn);            }            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);            info.setStringPermissions(permissions);            return info;        }        * */    }    @Test    public void test2(){
// 不使用配置文件的情况下: DefaultSecurityManager securityManager = new DefaultSecurityManager(); DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.cj.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/xdclass_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false"); ds.setUsername("root"); ds.setPassword("lchadmin"); JdbcRealm jdbcRealm = new JdbcRealm(); jdbcRealm.setPermissionsLookupEnabled(true); jdbcRealm.setDataSource(ds); securityManager.setRealm(jdbcRealm); // 将securityManager设置到当前运行环境中 SecurityUtils.setSecurityManager(securityManager); //获取当前subject(application应用的user) Subject subject = SecurityUtils.getSubject(); // 模拟用户输入 UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack","123"); // subject.login(usernamePasswordToken); System.out.println("认证结果(是否已授权):" subject.isAuthenticated()); //最终调用的是org.apache.shiro.authz.ModularRealmAuthorizer.hasRole方法 System.out.println("是否有role1角色:" subject.hasRole("role1")); System.out.println("是否有role2角色:" subject.hasRole("role2")); System.out.println("是否有root角色:" subject.hasRole("root")); //获取登录 账号 System.out.println("getPrincipal():" subject.getPrincipal()); //校验角色,没有返回值,校验不通过,直接抛出异常 subject.checkRole("role1"); System.out.println("=======subject.checkRole(\"role1\") passed=====" ); // user jack有video的find权限,执行通过 subject.checkPermission("video:find"); // 是否有video:find权限:true System.out.println("是否有video:find权限:" subject.isPermitted("video:find")); // 是否有video:delete权限:false System.out.println("是否有video:delete权限:" subject.isPermitted("video:delete")); //user jack没有video的删除权限,执行会报错:org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [video:delete] subject.checkPermission("video:delete"); }}

 

来源:https://www.icode9.com/content-4-601301.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
基于Spring框架的Shiro配置
SpringBoot+shiro整合学习之登录认证和权限控制
jfinal-shiro的shiro注解结合数据库url路径过滤,动态维护你的权限系统,支持ajax
Mysql 修改字段默认值
Spring Boot 极简集成 Shiro
源码分析shiro认证授权流程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服