第一章:Shiro 的基本使用(含示例代码)

第一章:Shiro 的基本使用(含示例代码)

Shiro官方:http://shiro.apache.org

第一章:Shiro 的基本使用(含示例代码)_第1张图片

示例代码:https://gitee.com/itwenke/spring-boot-demo/tree/master/shiro

第一章:Shiro 的基本使用(含示例代码)_第2张图片

框架介绍

Shiro是一个强大且易于使用的Java安全框架,用于身份验证、授权、加密和会话管理等安全功能。它提供了简单直观的API,使得开发人员能够轻松地集成安全功能到他们的应用程序中。Shiro的设计目标是使安全变得简单,同时提供高度的可定制性和可扩展性,以满足各种复杂的安全需求。

Shiro框架的核心概念包括:

  1. Subject:代表当前用户,可以是一个人、设备或者第三方服务。Subject可以执行身份验证和授权操作。

  2. SecurityManager:负责管理所有的Subject,是Shiro框架的核心。它协调着所有的安全操作,包括身份验证、授权、会话管理等。

  3. Realm:用于验证用户身份和获取用户的授权信息。Realm通常连接到后端的数据源,如数据库、LDAP等。

  4. SessionManager:管理用户的会话,包括创建、删除、过期等操作。

Shiro框架的优点包括简单易用、灵活性高、可定制性强、功能完善等。它可以与各种Java框架和技术无缝集成,如Spring、Servlet容器、JAX-RS等。因此,Shiro框架成为了许多Java应用程序的首选安全解决方案。

第一章:Shiro 的基本使用(含示例代码)_第3张图片

Realm 的基本使用

认证流程:
第一章:Shiro 的基本使用(含示例代码)_第4张图片

SimpleAccountRealm

  • 简介:SimpleAccountRealm是Shiro框架中的一个基本的Realm实现,它允许在代码中直接添加用户、角色和权限信息,而不需要连接到外部数据源。
  • 区别:SimpleAccountRealm是一个内存中的Realm,用户、角色和权限信息是在代码中硬编码的,适用于小型应用或者快速原型开发,但不适合大规模应用或者需要动态管理用户数据的场景。

具体代码操作:

public class Demo {

    @Test
    public void authen() {
        // 创建 SimpleAccountRealm
        SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
        simpleAccountRealm.addAccount("admin", "admin", "超级管理员", "物流管理员");

        // 创建 DefaultSecurityManager
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        // DefaultSecurityManager 与 SimpleAccountRealm 建立连接
        securityManager.setRealm(simpleAccountRealm);

        // Subject 和 DefaultSecurityManager 建立关系
        SecurityUtils.setSecurityManager(securityManager);

        // 获取 Subject
        Subject subject = SecurityUtils.getSubject();

        // 发起认证
        subject.login(new UsernamePasswordToken("admin", "admin"));
        // 用户名错误,抛出异常:org.apache.shiro.authc.UnknownAccountException
        // 密码错误,抛出异常:org.apache.shiro.authc.IncorrectCredentialsException

        // 判断是否认证成功
        System.out.println("是否认证成功:" + subject.isAuthenticated());

        // 校验权限
        System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));
        System.out.println("是否拥有物流管理员:" + subject.hasRole("物流管理员"));
        System.out.println("是否拥有商品管理员:" + subject.hasRole("商品管理员"));

        // 退出登录
        subject.logout();
        System.out.println("是否认证成功:" + subject.isAuthenticated());
    }
}

运行结果:

是否认证成功:true
是否拥有超级管理员角色:true
是否拥有物流管理员:true
是否拥有商品管理员:false
是否认证成功:false

IniRealm

  • 简介:IniRealm是从INI格式的配置文件中读取用户、角色和权限信息的Realm实现。INI文件中包含了用户、角色和权限的定义,可以通过配置文件灵活地管理用户数据。
  • 区别:IniRealm适用于基于INI配置文件的应用,可以方便地管理用户数据,但不适合大规模应用或者需要动态管理用户数据的场景。

具体代码操作:

shiro.ini 配置文件:

[users]
admin=admin,超级管理员,运营管理员,商品管理员
test=123456,商品管理员
[roles]
超级管理员=user:add,user:update,user:delete
商品管理员=perm1,perm2

验证:

public class Demo {

    @Test
    public void authen() {
        // 创建 SimpleAccountRealm
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");

        // 创建 DefaultSecurityManager
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        // DefaultSecurityManager 与 IniRealm 建立连接
        securityManager.setRealm(iniRealm);

        // Subject 和 DefaultSecurityManager 建立关系
        SecurityUtils.setSecurityManager(securityManager);

        // 获取 Subject
        Subject subject = SecurityUtils.getSubject();

        // 发起认证
        subject.login(new UsernamePasswordToken("admin", "admin"));
        System.out.println("是否认证通过:" + subject.isAuthenticated());

        // 角色校验
        System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));

        // 权限校验
        System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
        subject.checkPermission("user:update"); // 没有权限就抛异常:org.apache.shiro.authz.UnauthorizedException
    }
}

运行结果:

是否认证通过:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true

JdbcRealm

  • 简介:JdbcRealm是通过JDBC连接到数据库,从数据库中获取用户、角色和权限信息的Realm实现。它允许将用户数据存储在关系型数据库中,并通过SQL查询来获取用户身份和权限信息。
  • 区别:JdbcRealm适用于需要将用户数据存储在数据库中的应用,可以灵活地管理用户数据,并适用于大规模应用或者需要动态管理用户数据的场景。

具体代码操作:

public class Demo {

    @Test
    public void authen(){
        // 创建 JdbcRealm
        JdbcRealm jdbcRealm = new JdbcRealm();
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///shiro-jdbc");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        jdbcRealm.setDataSource(dataSource);

        // 开启权限校验
        jdbcRealm.setPermissionsLookupEnabled(true);

        // 创建 DefaultSecurityManager
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        // DefaultSecurityManager 与 SimpleAccountRealm 建立连接
        securityManager.setRealm(jdbcRealm);

        // Subject 和 DefaultSecurityManager 建立关系
        SecurityUtils.setSecurityManager(securityManager);

        // 获取 Subject
        Subject subject = SecurityUtils.getSubject();

        // 发起认证
        subject.login(new UsernamePasswordToken("admin", "admin"));

        // 判断是否认证成功
        System.out.println("是否认证成功:" + subject.isAuthenticated());

        // 角色校验
        System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));

        // 权限校验
        System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
    }
}

运行结果:

是否认证成功:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true

CustomRealm(自定义Realm)

强烈推荐!!!
强烈推荐!!!
强烈推荐!!!

  • 简介:CustomRealm是开发者根据自己的需求自定义的Realm实现,可以根据具体的业务逻辑和数据存储方式来实现用户身份验证和授权逻辑。
  • 区别:CustomRealm是灵活的自定义Realm,可以根据具体需求实现特定的用户认证和授权逻辑,适用于需要定制化用户数据管理的场景。

具体代码操作:

声明POJO类,继承AuthorizingRealm

public class CustomRealm extends AuthorizingRealm {

    {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("MD5");
        matcher.setHashIterations(1024);
        this.setCredentialsMatcher(matcher);
    }

    /**
     * 用户认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取用户名
        String username = (String) authenticationToken.getPrincipal();

        // 判断用户名(非空)
        if(username == null || username.equals("")){
            // 返回null,默认抛出一个异常:org.apache.shiro.authc.UnknownAccountException
            return null;
        }

        // 根据用户名查询用户
        User user = this.findUserByUsername(username);

        // 判断用户是否为null
        if(user == null) {
            return null;
        }

        // 声明 SimpleAuthenticationInfo 对象,并填充用户信息
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),"CustomRealm");

        // 设置盐
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));

        return simpleAuthenticationInfo;
    }

    /***
     * 授权认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取认证用户
        User user = (User) principalCollection.getPrimaryPrincipal();

        // 根据用户获取当前用户拥有的角色
        Set<String> roleSet = this.findRolesByUser(user);

        // 根据用户拥有的角色查询权限信息
        Set<String> permSet = this.findPermsByRoleSet(roleSet);

        // 声明 SimpleAuthorizationInfo 对象,并填充角色信息和权限信息
        SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
        simpleAuthenticationInfo.setRoles(roleSet);
        simpleAuthenticationInfo.setStringPermissions(permSet);

        return simpleAuthenticationInfo;
    }

    /**
     * 生成加盐的MD5密码
     */
    public static void main(String[] args) {
        System.out.println(new Md5Hash("admin", "abcdefg123456", 1024));
    }

    /**
     * 模拟数据库操作
     */
    private User findUserByUsername(String username) {
        if("admin".equals(username)){
            User user = new User();
            user.setId(1);
            user.setUsername("admin");
            user.setPassword("3e48d56a6fc20c50f589f562cdf20451");
            user.setSalt("abcdefg123456");
            return user;
        }
        return null;
    }

    /**
     * 模拟数据库操作
     */
    private Set<String> findRolesByUser(User user) {
        Set<String> set = new HashSet<>();
        set.add("超级管理员");
        set.add("运营管理员");
        return set;
    }

    /**
     * 模拟数据库操作
     */
    private Set<String> findPermsByRoleSet(Set<String> roleSet) {
        Set<String> set = new HashSet<>();
        set.add("user:add");
        set.add("user:update");
        return set;
    }
}

用户类:

@Data
public class User {

    private Integer id;

    private String username;

    private String password;

    private String salt;
}

验证:

public class Demo {

    @Test
    public void authen(){
        // 创建 JdbcRealm
        CustomRealm customRealm = new CustomRealm();

        // 创建 DefaultSecurityManager
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        // DefaultSecurityManager 与 SimpleAccountRealm 建立连接
        securityManager.setRealm(customRealm);

        // Subject 和 DefaultSecurityManager 建立关系
        SecurityUtils.setSecurityManager(securityManager);

        // 获取 Subject
        Subject subject = SecurityUtils.getSubject();

        // 发起认证
        subject.login(new UsernamePasswordToken("admin", "admin"));

        // 判断是否认证成功
        System.out.println("是否认证成功:" + subject.isAuthenticated());

        // 角色校验
        System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));

        // 权限校验
        System.out.println("是否拥有添加用户权限:" + subject.isPermitted("user:add"));
    }
}

运行结果:

是否认证成功:true
是否拥有超级管理员角色:true
是否拥有添加用户权限:true

你可能感兴趣的:(Shiro,安全框架,java,web安全)