zoukankan      html  css  js  c++  java
  • Java-Shiro(五):Shiro Realm讲解(二)IniRealm的用法、JdbcRelam的用法

    引入

    上一篇在讲解Realm简介时,介绍过Realm包含大概4类缺省的Realm,本章主要讲解:

    1)IniRealm的用法;

    2)JdbcRealm基于mysql   默认表及查询语句实现认证、授权;

    3)JdbcRealm基于mysql自定义表及查询语句实现认证、授权。

    4)自定义Realm。

    在上一张讲解时,截图了一张Realm的类图,这里需要重复引用下:

    从图中,我们可以看出AuthenticatingRealm是AuthorizingRealm的父类:

    1)AuthenticatingRealm类内部对外提供了抽象认证接口:

    2)AuthorizingRealm    类内部对外提供了抽象授权接口:

    3)因AuthorizingRealm继承了AuthenticationgRelam,因此AuthorizingRealm具有了认证、授权接口。

    因此后边讲解自定义Realm时,我们会采用继承 AuthorizingRealm的方式去实现自定义Realm。

    IniRealm的用法

    在Shiro缺省的几种实际上IniRealm和PropertiesRealm的用法最为类似。

    主要是将用户信息、用户角色、用户资源信息存储到相应的*.ini文件中,认证和授权时从文件中查找相应的数据是否存在。

    *.ini主要分为4个部分:[main]、[users]、[roles]、[urls]

    示例:
    shiro-config.ini文件:

    [main] 
    #authenticator 
    #配置验证器
    authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator 
    #配置策略
    authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy 
    #将验证器和策略关联起来
    authenticator.authenticationStrategy=$authenticationStrategy 
    securityManager.authenticator=$authenticator 
      
    #authorizer 
    authorizer=org.apache.shiro.authz.ModularRealmAuthorizer 
    permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver 
    authorizer.permissionResolver=$permissionResolver 
    securityManager.authorizer=$authorizer 
      
    #realm 
    dataSource=com.alibaba.druid.pool.DruidDataSource 
    dataSource.driverClassName=com.mysql.jdbc.Driver 
    dataSource.url=jdbc:mysql://localhost:3306/shiro 
    dataSource.username=root 
    dataSource.password=123456
    
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm 
    jdbcRealm.dataSource=$dataSource 
    jdbcRealm.permissionsLookupEnabled=true
    securityManager.realms=$jdbcRealm 
    [users] 
    #提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2
    zhangsan=123,admin,member
    lisi=1234,member
    
    [roles] 
    #提供了角色及权限之间关系的配置,角色=权限1,权限2
    admin=article:update,article:delete,article:query
    member=article:query
      
    [urls] 
    #用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器 
    /index.html = anon 
    /admin/** = authc, roles[admin], perms["article:query"] 

    1)[main]模块:

    主要负责shiro相关配置:securityManger,realm,credentialsMatcher,authenticator,authorizer等。
    给securityManger配置authenticator(认证器),authenticator.authenticationStrategy(认证器的多realm策略)
    给securityManger配置authorizer(授权器),authorizer.permissionResolver(授权器的资源解析器)
    给securityManger配置realms,realm(认证、授权 存储器).属性设置(JdbcRealm.dataSource/JdbcRealm.permissionLookupEnabled)
    给realm配置credentialsMatcher(凭证匹配器:它内部包含采用哪种方式进行加密:md5、sha256,slat[盐值],hashIterations[加密迭代多少次])

    2)[users]模块:
    提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2,示例:

    [users]
    zhangsan=123,admin,member lisi=1234,member

    3)[roles]模块:
    提供了角色及权限之间关系的配置,角色=权限1,权限2,示例:

    [roles]
    admin=article:update,article:delete,article:query member=article:query

    4)[urls]模块:
    用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器,示例:

    [urls]
    /index.html = anon /admin/** = authc, roles[admin], perms["article:query"]

    上边配置信息在shiro比较早点版本(shiro1.4.2就不是特别好用了)可使用IniSecurityManagerFactory进行加载:

    Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-config.ini"); 
    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); 
     
    //将SecurityManager设置到SecurityUtils 方便全局使用 
    SecurityUtils.setSecurityManager(securityManager); 
    Subject subject = SecurityUtils.getSubject(); 
    UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); 
    subject.login(token); 
      
    Assert.assertTrue(subject.isAuthenticated()); 

     实际上边配置shiro-config.xml中[main]配置信息等同于:

            DefaultSecurityManager securityManager = new DefaultSecurityManager();
    
            // #配置验证器
            ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
            // #配置策略
            AtLeastOneSuccessfulStrategy authenticationStrategy = new AtLeastOneSuccessfulStrategy();
            // #将验证器和策略关联起来
            authenticator.setAuthenticationStrategy(authenticationStrategy);
            securityManager.setAuthenticator(authenticator);
    
            // #授权器
            ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
            WildcardPermissionResolver permissionResolver = new WildcardPermissionResolver();
            authorizer.setPermissionResolver(permissionResolver);
            securityManager.setAuthorizer(authorizer);
    
            DruidDataSource dataSource = new DruidDataSource();
            {
                dataSource.setUsername("root");
                dataSource.setPassword("123456");
                dataSource.setUrl(
                        "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false");
                dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            }
    
            JdbcRealm jdbcRealm = new JdbcRealm();
            jdbcRealm.setDataSource(dataSource);
            // JdbcRealm.permissionsLookupEnabled 默认为false,必须设置为true才能进行角色的授权。
            jdbcRealm.setPermissionsLookupEnabled(true);
    
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("MD5");
            credentialsMatcher.setHashIterations(8);
            jdbcRealm.setCredentialsMatcher(credentialsMatcher);
            
            securityManager.setRealms(Arrays.asList(jdbcRealm));

    使用时,通过SecurityUtils与securityManager进行关联,然后获取Subject对象,通过subject进行认证验证,授权验证,退出认证。

            SecurityUtils.setSecurityManager(securityManager);
    
            Subject subject = SecurityUtils.getSubject();
    
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
            subject.login(token);
            System.out.println("是否通过认证:" + subject.isAuthenticated());
    
            System.out.println("是否拥有admin角色:" + subject.hasRole("admin"));
            // 必须设置JdbcRealm为jdbcRealm.setPermissionsLookupEnabled(true)
            // 是否拥有修改的权限
            System.out.println("是否拥有user:update角色:" + subject.isPermitted("user:update"));
    
            subject.logout();
            System.out.println("是否通过认证:" + subject.isAuthenticated());

    IniRealm的使用示例:

    1)认证用法:

    配置文件 shiroAuthenticator.ini

    #用来认证
    #============================
    #设置用户,可设置多名用户
    [users]
    # 用户名=密码
    zhangsan=123
    lisi=1234

    用法测试:

        /**
         * 测试认证
         */
        @Test
        public void testAuthenticator() {
            // 1)根据IniRealm进行数据读取 *.ini 配置,另外也可以通过JdbcRealm读取数据中存储的信息,也可以采用内存存储方式,还可以用户自定义。
            // Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager需验证用户身份,那么它需要从Realm获取响应的用户进行比较以确定用户身份是否合法;
            // 也需要从Realm得到用户相应的角色、权限进行验证用户是否能进行操作;
            // 可以把Realm看成DataSource。
            Realm iniRealm = new IniRealm("classpath:shiroAuthenticator.ini");
    
            // 2) 管理所有的Subject,负责认证、授权、会话以及缓存的管理。
            // SecurityManager:安全管理器,即所有与安全有关的操作都会与SecurityManager交互;
            // 且其管理所有Subject;
            // 可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC中DispatcherServlet的角色。
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(iniRealm);
    
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            // Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject。
            // Subject代表了当前"用户",这个用户不一定就是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;
            // 与Subject的所有交互都委托给SecurityManager;
            // Subject其实是一个门面,SecurityManager才是实际的执行者;
            Subject subject = SecurityUtils.getSubject();
    
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
            // 进行认证
            subject.login(token);
    
            System.out.println("是否认证通过:" + subject.isAuthenticated());
        }

    2)授权的用法:

    配置文件 shiroAuthorizer.ini

    #用来授权
    #===========================
    #设置用户及用户角色
    [users]
    # 用户名=密码,角色
    zhangsan=123,admin
    lisi=1234,member
    
    #设置角色与角色权限
    [roles]
    # 角色=资源1,资源2
    admin=user:delete,user:update,user:query
    member=user:query

    用法测试:

        /**
         * 测试认证+授权
         */
        @Test
        public void testAuthorizer() {
            Realm iniRealm = new IniRealm("classpath:shiroAuthorizer.ini");
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(iniRealm);
    
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            Subject subject = SecurityUtils.getSubject();
    
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
            // 调用 Realm#getAuthenticationinfo()
            subject.login(token);
    
            System.out.println("是否认证通过:" + subject.isAuthenticated());
    
            // 调用 Realm#getAuthorizationinfo()
            System.out.println("是否授权admin角色:" + subject.hasRole("admin"));
            System.out.println("是否拥有user:update资源:" + subject.isPermitted("user:update"));
            System.out.println("是否拥有user:delete资源:" + subject.isPermitted("user:delete"));
            System.out.println("是否拥有user:create资源:" + subject.isPermitted("user:create"));
    
            subject.logout();
    
            System.out.println("是否认证通过:" + subject.isAuthenticated());
    
            System.out.println("是否授权admin角色:" + subject.hasRole("admin"));
            System.out.println("是否拥有user:update资源:" + subject.isPermitted("user:update"));
            System.out.println("是否拥有user:delete资源:" + subject.isPermitted("user:delete"));
            System.out.println("是否拥有user:create资源:" + subject.isPermitted("user:create"));
        }

    JdbcRealm的用法

    使用JdbcRealm内部默认表和查询SQL

    JdbcRealm实际上在代码内部缺省在关系数据库中存在三张表:

    `users`{id,username,password,password_salt}
    `user_roles`{id,username,role_name}
    `roles_permissions`{id,role_name,permission}

    其实,从JdbcRealm内部定义的查询语句可以看出内置表结构:

        /**
         * The default query used to retrieve account data for the user.
         */
        protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
        
        /**
         * The default query used to retrieve account data for the user when {@link #saltStyle} is COLUMN.
         */
        protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
    
        /**
         * The default query used to retrieve the roles that apply to a user.
         */
        protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
    
        /**
         * The default query used to retrieve permissions that apply to a particular role.
         */
        protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";

    JdbcRealm使用时,需要在关系数据库中创建默认的那三张表,然后配置信息写入到对应表中。

    -- ----------------------------
    -- Table structure for users
    -- ----------------------------
    DROP TABLE IF EXISTS `users`;
    CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL,
      `password` varchar(64) NOT NULL,
      `password_salt` varchar(64) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_username` (`username`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of users
    -- ----------------------------
    BEGIN;
    INSERT INTO `users` VALUES (1, 'zhangsan', '0349a8cd4b237e190e6e4b471e214ef3','eC4mL7bZ5sN8');
    INSERT INTO `users` VALUES (2, 'lisi', '4d7a330008c2191c4c76b9b3dd59841d','qN3fT4eK2yQ9');
    COMMIT;
    
    -- ----------------------------
    -- Table structure for user_roles
    -- ----------------------------
    DROP TABLE IF EXISTS `user_roles`;
    CREATE TABLE `user_roles` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL,
      `role_name` varchar(64) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_role_name` (`role_name`),
      KEY `idx_username` (`username`),
      KEY `idx_role_name` (`role_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user_roles
    -- ----------------------------
    BEGIN;
    INSERT INTO `user_roles` VALUES (1, 'zhangsan', 'admin');
    INSERT INTO `user_roles` VALUES (2, 'lisi', 'member');
    COMMIT;
    
    -- ----------------------------
    -- Table structure for roles_permissions
    -- ----------------------------
    DROP TABLE IF EXISTS `roles_permissions`;
    CREATE TABLE `roles_permissions` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `role_name` varchar(64) DEFAULT NULL,
      `permission` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_role_name_permission` (`role_name`,`permission`),
      KEY `idx_role_name` (`role_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of roles_permissions
    -- ----------------------------
    BEGIN;
    INSERT INTO `roles_permissions` VALUES (2, 'admin', 'user:delete');
    INSERT INTO `roles_permissions` VALUES (1, 'admin', 'user:update');
    INSERT INTO `roles_permissions` VALUES (3, 'member', 'user:query');
    COMMIT;

    使用测试代码:

        /**
         * 使用默认 JdbcRealm 中相关表进行相关登录认证、使用默认的sql语句进行授权
         */
        @Test
        public void testJdbcRealmByDefaultDBConfiguration() {
            DefaultSecurityManager securityManager = new DefaultSecurityManager();
    
            // #配置验证器
            ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
            // #配置策略
            AtLeastOneSuccessfulStrategy authenticationStrategy = new AtLeastOneSuccessfulStrategy();
            // #将验证器和策略关联起来
            authenticator.setAuthenticationStrategy(authenticationStrategy);
            securityManager.setAuthenticator(authenticator);
    
            // #授权器
            ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
            WildcardPermissionResolver permissionResolver = new WildcardPermissionResolver();
            authorizer.setPermissionResolver(permissionResolver);
            securityManager.setAuthorizer(authorizer);
    
            DruidDataSource dataSource = new DruidDataSource();
            {
                dataSource.setUsername("root");
                dataSource.setPassword("123456");
                dataSource.setUrl(
                        "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false");
                dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            }
    
            JdbcRealm jdbcRealm = new JdbcRealm();
            jdbcRealm.setDataSource(dataSource);
            // JdbcRealm.permissionsLookupEnabled 默认为false,必须设置为true才能进行角色的授权。
            jdbcRealm.setPermissionsLookupEnabled(true);
    
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("MD5");
            credentialsMatcher.setHashIterations(8);
            jdbcRealm.setCredentialsMatcher(credentialsMatcher);
            
            securityManager.setRealms(Arrays.asList(jdbcRealm));
    
            SecurityUtils.setSecurityManager(securityManager);
            Subject subject = SecurityUtils.getSubject();
    
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
            subject.login(token);
            System.out.println("是否通过认证:" + subject.isAuthenticated());
    
            System.out.println("是否拥有admin角色:" + subject.hasRole("admin"));
            // 必须设置JdbcRealm为jdbcRealm.setPermissionsLookupEnabled(true)
            // 是否拥有修改的权限
            System.out.println("是否拥有user:update角色:" + subject.isPermitted("user:update"));
    
            subject.logout();
            System.out.println("是否通过认证:" + subject.isAuthenticated());
        }

    打印信息:

    log4j:WARN No appenders could be found for logger (com.alibaba.druid.pool.DruidDataSource).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    是否通过认证:true
    是否拥有admin角色:true
    是否拥有user:update角色:true
    是否通过认证:false

    JdbcRealm使用自定义表和插叙SQL

    需要在关系数据自定义三张表:my_user,my_role,my_permission。

    -- ----------------------------
    -- Table structure for my_user
    -- ----------------------------
    DROP TABLE IF EXISTS `my_user`;
    CREATE TABLE `my_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL,
      `password` varchar(64) NOT NULL,
      `password_salt` varchar(64) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_username` (`username`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of my_user
    -- ----------------------------
    BEGIN;
    INSERT INTO `my_user` VALUES (1, 'zhangsan', '0349a8cd4b237e190e6e4b471e214ef3','eC4mL7bZ5sN8');
    INSERT INTO `my_user` VALUES (2, 'lisi', '4d7a330008c2191c4c76b9b3dd59841d','qN3fT4eK2yQ9');
    COMMIT;
    
    -- ----------------------------
    -- Table structure for my_role
    -- ----------------------------
    DROP TABLE IF EXISTS `my_role`;
    CREATE TABLE `my_role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL,
      `role_name` varchar(64) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_role_name` (`role_name`) USING BTREE,
      KEY `idx_username` (`username`),
      KEY `idx_role_name` (`role_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of my_role
    -- ----------------------------
    BEGIN;
    INSERT INTO `my_role` VALUES (1, 'zhangsan', 'admin');
    INSERT INTO `my_role` VALUES (2, 'lisi', 'member');
    COMMIT;
    -- ----------------------------
    -- Table structure for my_permission
    -- ----------------------------
    DROP TABLE IF EXISTS `my_permission`;
    CREATE TABLE `my_permission` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `role_name` varchar(64) DEFAULT NULL,
      `permission` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `un_idx_role_name_permission` (`role_name`,`permission`) USING BTREE,
      KEY `idx_role_name` (`role_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of my_permission
    -- ----------------------------
    BEGIN;
    INSERT INTO `my_permission` VALUES (2, 'admin', 'user:delete');
    INSERT INTO `my_permission` VALUES (1, 'admin', 'user:update');
    INSERT INTO `my_permission` VALUES (3, 'member', 'user:query');
    COMMIT;

    使用测试:

        @Test
        public void testJdbcRealmByMyDBConfiguration() {
            DruidDataSource dataSource = new DruidDataSource();
            {
                dataSource.setUsername("root");
                dataSource.setPassword("123456");
                dataSource.setUrl(
                        "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false");
                dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            }
    
            JdbcRealm jdbcRealm = new JdbcRealm();
            jdbcRealm.setDataSource(dataSource);
            // JdbcRealm.permissionsLookupEnabled 默认为false,必须设置为true才能进行角色的授权。
            jdbcRealm.setPermissionsLookupEnabled(true);
            jdbcRealm.setSaltStyle(SaltStyle.COLUMN); // 启用表 password_salt 字段
            
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("MD5");
            credentialsMatcher.setHashIterations(8);
            jdbcRealm.setCredentialsMatcher(credentialsMatcher);
            
            jdbcRealm.setAuthenticationQuery("select `password`,`password_salt` from `my_user` where `username`=? ");
            jdbcRealm.setUserRolesQuery("select `role_name` from `my_role` where `username`=? ");
            jdbcRealm.setPermissionsQuery("select `permission` from `my_permission` where role_name=? ");
    
            // 创建SecurityManager;
            DefaultSecurityManager securityManager = new DefaultSecurityManager(jdbcRealm);
    
            SecurityUtils.setSecurityManager(securityManager);
            Subject subject = SecurityUtils.getSubject();
    
            subject.logout();
            UsernamePasswordToken token = new UsernamePasswordToken("lisi", "1234");
            subject.login(token);
    
            System.out.println("是否通过认证:" + subject.isAuthenticated());
            System.out.println("是否已经授权member角色:" + subject.hasRole("member"));
            System.out.println("是否已经授权admin角色:" + subject.hasRole("admin"));
    
            System.out.println("是否已经拥有user:create资源:" + subject.isPermitted("user:create"));
            System.out.println("是否已经拥有user:update资源:" + subject.isPermitted("user:update"));
            System.out.println("是否已经拥有user:delete资源:" + subject.isPermitted("user:delete"));
            System.out.println("是否已经拥有user:query资源:" + subject.isPermitted("user:query"));
    
            subject.logout();
            System.out.println("是否通过认证:" + subject.isAuthenticated());
        }

    打印结果:

    log4j:WARN No appenders could be found for logger (com.alibaba.druid.pool.DruidDataSource).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    是否通过认证:true
    是否已经授权member角色:true
    是否已经授权admin角色:false
    是否已经拥有user:create资源:false
    是否已经拥有user:update资源:false
    是否已经拥有user:delete资源:false
    是否已经拥有user:query资源:true
    是否通过认证:false
  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/12089148.html
Copyright © 2011-2022 走看看