三、Shiro之Realm(数据源)

  Shiro数据源有三种,一种是IniRealm(配置文件数据源)、一种是JdbcRealm(数据库数据源)、一种是自定义Realm。

  综下所述,所谓的数据源,就是提供真实的用户名、密码、角色、权限,具体的验证逻辑由Shiro进行。

一、IniRealm(配置文件数据源)

(一)创建user.ini

[users]
root=root,admin
[roles]
admin=user:delete

(二)进行用户、角色、权限验证

public class IniRealmTest {
    @Test
    public void testIniRealm(){
        //1、创建SecurityManager对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //2、创建IniRealm数据源(相当于用户名、密码、权限配置文件)
        IniRealm realm = new IniRealm("classpath:user.ini");

        //3、设置数据源
        securityManager.setRealm(realm);

        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        AuthenticationToken token = new UsernamePasswordToken("root", "root", "admin");
        subject.login(token);

        System.out.println();
        //验证该用户是否有该角色
        subject.checkRole("admin");
        //验证该用户是否有该权限
        subject.checkPermission("user:delete");
    }
}

二、JdbcRealm(数据库数据源)

  1、要想进行权限验证,必须进行该项设置:jdbcRealm.setPermissionsLookupEnabled(true)

  2、JdbcRealm提供默认的用户、角色、权限查询语句,但是要求建的表名、列名必须和默认查询语句保持一致,否则就需要自定义查询语句,具体参见下方代码!

public class JdbcRealmTest {
    private static DruidDataSource dataSource;
    static {
        dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/shiro");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
    }
    @Test
    public void testJdbcRealm(){
        //1、初始化JdbcRealm
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        /**
         *     重点:JdbcRealm默认不开启权限检查,若要判断某角色是否有某样权限,需要开启此设置,否则会由于无法检查权限表,
         * 导致查询到的权限为空。
         */
        jdbcRealm.setPermissionsLookupEnabled(true);

        //(1)自定义查询密码(若不自定义,JdbcRealm有默认查询语句)
        String authenticationQuery = "select password from users where username = ?";
        jdbcRealm.setAuthenticationQuery(authenticationQuery);
        //(2)自定义查询角色(若不自定义,JdbcRealm有默认查询语句)
        String userRolesQuery = "select role_name from user_roles where username = ?";
        jdbcRealm.setUserRolesQuery(userRolesQuery);
        //(3)自定义查询权限(若不自定义,JdbcRealm有默认查询语句)
        String permissionsQuery = "select permission from roles_permissions where role_name = ?";
        jdbcRealm.setPermissionsQuery(permissionsQuery);

        //2、创建SecurityManager
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //3、设置数据源
        securityManager.setRealm(jdbcRealm);

        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        AuthenticationToken token = new UsernamePasswordToken("root", "root");
        subject.login(token);

        System.out.println(subject.isAuthenticated());

        subject.checkRole("admin");
        subject.checkPermission("user:delete");
    }
}

三、自定义Realm

1、创建自定义数据源类CustomRealm

public class CustomRealm extends AuthorizingRealm {
    private Map<String, String> userMap = new HashMap<String, String>();
    {
        userMap.put("root", "root");
        userMap.put("mark", "1234");
        //设置数据源的名称
        super.setName("customRealm");
    }

    /**
     * 授权验证(返回数据库中真实的角色、权限)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        Set<String> roles = getRolesByUsername(username);
        Set<String> permissions = getPermissionsByUsername(username);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 认证验证(返回数据库中真实的用户名、密码)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String)token.getPrincipal();
        String password = getPasswordByUsername(username);
        if (password == null){
            return null;
        }
        //参数一:用户名  参数二:密码   参数三:自定义Realm的名称(在构造函数中设置名称super.setName("customRealm"))
        return new SimpleAuthenticationInfo(username, password, "customRealm");
    }

    private String getPasswordByUsername(String username){
        return userMap.get(username);
    }


    private Set<String> getRolesByUsername(String username){
        Set<String> roles = new HashSet<String>();
        roles.add("admin");
        roles.add("guest");
        return roles;
    }

    private Set<String> getPermissionsByUsername(String username){
        Set<String> permissions = new HashSet<String>();
        permissions.add("user:delete");
        permissions.add("user:update");
        return permissions;
    }
}

2、测试

public class CustomRealmTest {
    @Test
    public void testCustomRealm(){
        CustomRealm customRealm = new CustomRealm();
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        securityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
        AuthenticationToken token = new UsernamePasswordToken("root", "root");
        subject.login(token);
        System.out.println(subject.isAuthenticated());
        subject.checkRoles("admin", "guest");

        subject.checkPermission("user:delete");
    }
}

猜你喜欢

转载自blog.csdn.net/panchang199266/article/details/82469495