Java Apache Shiro安全框架快速开发详解流程

Java Apache Shiro安全框架快速开发详解流程

什么是Apache Shiro

Apache Shiro是一个跨应用程序、支持单点登录、支持身份验证和访问控制框架,可以解决应用程序的安全问题。
Shiro的核心是将应用程序的用户身份、安全验证、访问控制等功能组合起来实现一个完整的安全框架。
使用Shiro开发的应用程序能够快速、安全地集成身份验证、安全验证、单点登录等功能。

Shiro框架的组件

Shiro由以下组件组成:

  • Subject:应用程序中的用户抽象对象,封装了与用户相关的对象和操作。

  • SecurityManager:Shiro框架的核心,用户管理、安全认证、访问控制等功能都与SecurityManager相关。

  • Authenticator:用于验证用户身份,提供不同的验证策略,如密码验证、指纹验证等。

  • Authorizer:用于授权用户访问资源,提供多种授权策略。

  • Realm:Shiro对数据源的抽象,用于获取用户身份认证信息和访问控制数据,可以将用户信息存储在数据库、LDAP或其他数据源中。

  • SessionManager:会话管理器,负责管理用户会话,可以定制不同的会话管理策略,如Cookie会话管理、URL会话跟踪等。

Shiro集成框架

在Java开发中,Shiro常常集成在一些框架中,如Spring、Struts等,通过集成Shiro,可以轻松地实现应用程序的安全模块。

下面就以Spring集成Shiro框架为例,介绍Shiro框架的快速开发流程。

快速搭建Shiro框架

在Spring应用程序中集成Shiro框架,通常需要完成以下步骤:

  1. 添加Shiro依赖:
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-all</artifactId>
    <version>1.7.0</version>
</dependency>
  1. 配置Shiro相关组件:
<!-- 配置SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm" />
</bean>

<!-- 配置Realm -->
<bean id="myRealm" class="xx.xx.xxx.MyRealm">
    <!-- 配置数据源 -->
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置Shiro过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <!-- 配置过滤规则 -->
    <property name="filterChainDefinitions">
        <value>
            /login.jsp = anon
            /logout = logout
            /** = authc
        </value>
    </property>
    <!-- 配置登录URL -->
    <property name="loginUrl" value="/login.jsp" />
    <!-- 配置成功登录后的URL -->
    <property name="successUrl" value="/index.jsp" />
    <!-- 配置未登录时的URL -->
    <property name="unauthorizedUrl" value="/unauthorized.jsp" />
</bean>
  1. 编写自定义Realm:
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 获取当前用户的角色和权限信息,并添加到authorizationInfo中
        User user = (User)principals.getPrimaryPrincipal();
        Set<String> roleNames = userService.findRoleNamesByUsername(user.getUsername());
        authorizationInfo.setRoles(roleNames);
        Set<String> permissions = userService.findPermissionsByUsername(user.getUsername());
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        // 根据用户名和密码查询用户信息
        User user = userService.findByUsernameAndPassword(upToken.getUsername(), new String(upToken.getPassword()));
        if (user != null) {
            // 如果用户存在返回一个身份认证信息
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
            return authenticationInfo;
        }
        throw new UnknownAccountException("用户名或密码错误");
    }
}

以上代码中,MyRealm类中的doGetAuthenticationInfo方法用于根据用户名和密码查询用户信息,如果找到用户信息则返回一个身份认证信息。
doGetAuthorizationInfo方法用于根据PrincipalCollection对象获取当前用户的角色和权限信息,并添加到相应的授权信息中。

  1. 使用Shiro相关API实现身份验证和访问控制:
// 获取Subject对象
Subject subject = SecurityUtils.getSubject();
// 构造UsernamePasswordToken对象
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
    // 身份验证
    subject.login(token);
} catch (AuthenticationException e) {
    // 身份验证失败
}
if (subject.isAuthenticated()) {
    // 访问控制
    if (subject.hasRole("admin")) {
        // admin用户的操作
    }
    if (subject.isPermitted("user:create")) {
        // 创建用户操作
    }
}

以上代码中,使用SecurityUtils.getSubject()方法获取当前用户对象,使用UsernamePasswordToken构造方法构造身份认证信息。
通过subject.login(token)方法进行身份验证,subject.hasRole()和subject.isPermitted()方法进行访问控制。

示例1:使用Shiro实现用户登录认证

  1. 创建login.jsp文件,并添加一个简单的表单用于用户登录:
<form action="/login" method="post">
    <input type="text" name="username" placeholder="用户名">
    <input type="password" name="password" placeholder="密码">
    <input type="submit" value="登录">
</form>
  1. 在Spring应用程序中配置Shiro相关组件,并添加用户登录控制器:
@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(HttpServletRequest request) {
        // 获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        // 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 构造UsernamePasswordToken对象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            // 身份验证
            subject.login(token);
            // 身份验证成功跳转到首页
            return "redirect:/index";
        } catch (AuthenticationException e) {
            // 身份验证失败跳转到登录页面,显示错误信息
            request.setAttribute("error", "用户名或密码错误");
            return "login";
        }
    }
}
  1. 在MyRealm类中实现doGetAuthenticationInfo方法用于根据用户名和密码查询用户信息:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    UsernamePasswordToken upToken = (UsernamePasswordToken) token;
    // 根据用户名和密码查询用户信息
    User user = userService.findByUsernameAndPassword(upToken.getUsername(), new String(upToken.getPassword()));
    if (user != null) {
        // 如果用户存在返回一个身份认证信息
        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        return authenticationInfo;
    }
    throw new UnknownAccountException("用户名或密码错误");
}
  1. 运行应用程序并访问/login,输入用户名和密码进行登录认证。

示例2:使用Shiro实现角色授权和资源保护

  1. 在数据库中创建用户、角色和权限三张表,并添加测试数据:
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL DEFAULT '',
  `password` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `user` (`id`, `username`, `password`) VALUES
    (1, 'admin', 'admin'),
    (2, 'user', 'user');

INSERT INTO `role` (`id`, `name`) VALUES
    (1, 'admin'),
    (2, 'user');

INSERT INTO `permission` (`id`, `name`) VALUES
    (1, 'user:read'),
    (2, 'user:create'),
    (3, 'user:update'),
    (4, 'user:delete');
  1. 在MyRealm类中实现doGetAuthorizationInfo方法,使用userService.findRoleNamesByUsername()和userService.findPermissionsByUsername()方法查询当前用户的角色和权限信息,并添加到authorizationInfo对象中:
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    User user = (User)principals.getPrimaryPrincipal();
    Set<String> roleNames = userService.findRoleNamesByUsername(user.getUsername());
    authorizationInfo.setRoles(roleNames);
    Set<String> permissions = userService.findPermissionsByUsername(user.getUsername());
    authorizationInfo.setStringPermissions(permissions);
    return authorizationInfo;
}
  1. 在Spring应用程序中配置Shiro相关组件,并添加用户列表控制器:
@Controller
public class UserController {
    @RequestMapping("/users")
    public String list() {
        // 访问控制,如果用户没有"admin"角色或"users:view"权限,则禁止访问
        Subject subject = SecurityUtils.getSubject();
        if (!subject.hasRole("admin") && !subject.isPermitted("users:view")) {
            throw new UnauthorizedException("没有访问权限");
        }
        // 查询用户列表,并返回到users.jsp页面
        List<User> userList = userService.findAll();
        return "users";
    }
}
  1. 在Spring应用程序中修改Shiro过滤器,使用perms和roles配置用户访问控制规则:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm" />
    <property name="sessionManager" ref="sessionManager" />
</bean>

<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <property name="globalSessionTimeout" value="3600000" />
    <property name="deleteInvalidSessions" value="true" />
    <property name="sessionDAO" ref="sessionDAO" />
</bean>

<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
    <property name="cacheManager" ref="cacheManager" />
</bean>

<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="filterChainDefinitions">
        <value>
            /login.jsp = anon
            /logout = logout
            /users = authc, perms[users:view], roles[admin]
            /** = authc
        </value>
    </property>
    <property name="loginUrl" value="/login.jsp" />
    <property name="successUrl" value="/index.jsp" />
    <property name="unauthorizedUrl" value="/unauthorized.jsp" />
</bean>
  1. 运行应用程序并访问/users,如果当前用户没有"admin"角色或者"users:view"权限,则禁止访问;如果有访问权限,则显示用户列表。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java Apache Shiro安全框架快速开发详解流程 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • linux下安装oracle后使用命令行启动的方法 linux启动oracle

    下面是在Linux下安装Oracle并使用命令行启动的详细攻略: 准备工作 下载Oracle安装包,需要根据自己的机器配置选择合适的版本。 安装所需依赖,包括开发工具、库文件等。可以通过yum安装。 安装过程 解压Oracle安装包,并运行 runInstaller 脚本。 在安装向导的界面中,按照提示设置必要参数,如安装路径、数据库名称、端口号等。 对于该…

    database 2023年5月22日
    00
  • Mybatis中Mapper标签总结大全

    下面我将详细讲解”Mybatis中Mapper标签总结大全”的完整攻略。 一、什么是Mapper标签 Mapper标签是Mybatis中最为重要、最为核心的标签,用于编写SQL映射语句、处理结果映射等操作,是实现Mybatis操作数据库的关键。 二、Mapper标签的使用方式 1.使用Mapper标签的四个步骤 使用Mapper标签一般是通过以下四个步骤来完…

    database 2023年5月21日
    00
  • PHP与SQL语句常用大全

    PHP与SQL语句常用大全 PHP的SQL语句通常用于与数据库交互,包括数据查询、数据更新、数据插入等操作。下面是一些常用的SQL语句及其PHP实现。 数据库连接 连接数据库是操作数据库的第一步,可以使用mysqli或PDO扩展连接数据库。 mysqli扩展 $mysqli = new mysqli("localhost", "…

    database 2023年5月21日
    00
  • MySQL为JSON字段创建索引方式(Multi-Valued Indexes 多值索引)

    MySQL 5.7版本以后开始支持JSON数据类型,而JSON类型的字段数据是半结构化的数据。在使用半结构化字段类型的时候,针对这类字段的索引也就成为了必需的操作。 MySQL 提供了两种类型的 JSON 字段索引: Generated Columns Based on JSON Conditions Multi-Valued Indexes 本文主要介绍 …

    database 2023年5月22日
    00
  • Linux利用UDF库实现Mysql提权

    Linux利用UDF库实现MySQL提权攻略 背景 MySQL是一款常用的关系型数据库管理系统,为了提升服务器安全性能,往往会限制MySQL普通用户的权限。但是,如果攻击者能够获得了MySQL普通用户的访问权限,就可以利用MySQL UDF(User Defined Function)提权,获得root权限进行控制服务器。 实现步骤 1. 获取UDF库文件 …

    database 2023年5月22日
    00
  • Linux文件查找命令总结(上篇)

    下面给出对“Linux文件查找命令总结(上篇)”的详细讲解。 Linux文件查找命令总结(上篇) 1. find命令 find命令是Linux中最强大的文件查找命令之一。使用该命令可以在文件系统中查找符合条件的文件。 1.1 命令格式 find [path] [options] [conditions] path表示查找的起始目录,可以是绝对路径或相对路径。…

    database 2023年5月22日
    00
  • 关于MySQL报警的一次分析处理详解

    关于MySQL报警的一次分析处理详解 MySQL作为常用的关系型数据库,其可靠性和稳定性备受关注。然而,随着数据量和访问量的增加,MySQL问题的发生是不可避免的。本篇文章将详细介绍一次MySQL报警的分析和处理。 报警信息 MySQL出现报警是因为监控系统发现MySQL的某些指标出现异常。具体的报警信息如下: 警报名称: mysql.qps 当前数据: 1…

    database 2023年5月22日
    00
  • Ubuntu安装MySQL5.7并配置数据存储路径的方法步骤

    下面是详细的Ubuntu安装MySQL5.7并配置数据存储路径的方法步骤攻略。 下载并安装MySQL5.7 步骤1:在Ubuntu终端中更新APT软件包 在终端中输入以下命令更新APT软件包: sudo apt-get update 步骤2:下载并安装MySQL5.7 在终端中输入以下命令下载并安装MySQL5.7: sudo apt-get install…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部