墨风如雪博客

  • 源码小店
  • 导航站
  • 登录
  • java
  • 资源分享
让AI使用变得如此简单
  1. 首页
  2. java
  3. 正文

java 安全框架技术Apache Shiro解析

2023年 5月 7日 157点热度 0人点赞 0条评论

Apache Shiro是什么?

Apache Shiro 是一个强大且易于使用的开源Java安全框架,它提供了身份验证(身份验证)、授权(访问控制)和加密服务,可以帮助开发人员构建安全可靠的应用程序。

身份验证:Apache Shiro 可以轻松地处理身份验证,支持多种身份验证策略,例如基于表单、BASIC、DIGEST、OAuth、LDAP 和 Active Directory 等方式进行身份验证。

授权:基于角色和权限的访问控制是应用程序安全的基础,而 Apache Shiro 提供了丰富的授权功能,可以帮助开发人员快速实现不同的访问控制策略。

加密服务:Apache Shiro 提供了各种加密服务,包括哈希、加密、解密等功能,可以帮助应用程序保护敏感的数据和信息。

除此之外,Apache Shiro 还提供了会话管理、缓存支持等功能,可以大大简化应用程序的安全集成工作,提高应用的可靠性和安全性。

Apache Shiro解决的问题

Apache Shiro是一个强大的Java安全框架,它主要用于解决应用程序的安全性问题。它提供了一组可重用的安全组件,可以轻松地将它们集成到不同类型的应用程序中。Shiro框架提供了一种简单而直观的方式,让开发者可以在应用程序中实现安全性功能,包括身份验证、授权、加密和会话管理等方面。

具体来说,Apache Shiro主要解决以下问题:

1.身份验证:Shiro提供了一种简单的身份验证框架,可以轻松地验证用户的身份,例如用户名和密码等信息。

2.授权:通过Shiro,开发者可以轻松实现基于用户的授权管理。开发者可以将用户和角色之间建立关联,定义权限和资源,将这些授权信息与用户身份验证一起使用,保护应用程序的资源不被未经授权的用户访问。

3.会话管理:Shiro提供了一套全面的会话管理功能,为开发者提供了一个可靠的连接管理器,保证在应用程序与客户端之间的会话中,不会遇到任何问题。

4.加密:Apache Shiro为各种常见的加密需求提供了一组可重用的安全组件。这些组件可以让开发者更轻松地实现数据的加密、解密和签名等操作。

总之,Apache Shiro是一个强大而可靠的安全框架,它可以帮助开发者构建安全性高的应用程序,有效地解决常见的安全问题。它的缺点则是需要配置较多,较难使用。

Apache Shiro 的数据模型

Apache Shiro 的数据模型有三种模式:Subject,权限和角色。

1. Subject 模式:

Subject 模式是 Apache Shiro 的核心概念,它表示系统中的当前用户。所有的安全操作都是在 Subject 的上下文中进行的。Subject 模式有以下几种常用的命令:

  • 登录:Subject.login(AuthenticationToken token)。

  • 登出:Subject.logout()。

  • 是否已登录:Subject.isAuthenticated()。

  • 是否具有某种角色:Subject.hasRole(String roleIdentifier)。

  • 是否具有某种权限:Subject.isPermitted(String permission)。

2. 权限模式:

权限模式定义了系统内可以进行的所有操作,包括访问资源、操作资源等。权限模式在 Shiro 中是基于字符串的,开发人员可以根据实际情况自定义权限字符串。权限模式有以下几种常用的命令:

  • 添加权限:securityManager.add(new Permission(“permissionString”))。

  • 移除权限:securityManager.remove(new Permission(“permissionString”))。

  • 查询权限:securityManager.isPermitted(subject, new Permission(“permissionString”))。

3. 角色模式:

角色模式定义了系统内可以使用的角色,它是对权限集合的一种封装。一个用户可以拥有多个角色,一个角色可以包含多个权限。角色模式有以下几种常用的命令:

  • 创建角色:Role role = securityManager.createRole(“roleIdentifier”)。

  • 删除角色:securityManager.deleteRole(role)。

  • 查询角色:securityManager.getRole(“roleIdentifier”)。

总的来说,Apache Shiro 的数据模型有三种模式:Subject,权限和角色,通过这些模式可以实现灵活的安全控制。开发人员可以根据自己的实际需求,使用适合自己的模式来进行安全控制。

Apache Shiro使用可能遇到的问题

问题1:无效的用户凭证

问题原因: 可能是用户名或密码不正确,也可能是存储用户凭证的数据源出现问题。

解决办法: 检查用户名和密码是否正确,并确保数据源可以正常访问。另外,可以使用Shiro提供的加密方法来确保用户凭证的安全性,例如将密码使用MD5或SHA-1等算法加密后再存储。

代码示例:

//创建用户名和密码
String username = "admin";
String password = "123456";

//将密码使用MD5算法加密
String hashedPassword = new SimpleHash("md5", password).toHex();

//设置用户凭证
UsernamePasswordToken token = new UsernamePasswordToken(username, hashedPassword);

//进行登录认证
Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

问题2:授权失败

问题原因: 可能是当前用户没有足够的权限或角色来执行所请求的操作,也可能是授权配置出现问题。

解决办法: 检查用户角色和权限配置是否正确,并确保用户的身份已经被认证。如果需要动态授权,可以在代码中使用Shiro提供的授权API来实现。

代码示例:

//检查用户是否有某个角色
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.hasRole("admin")) {
   //执行管理员操作
} else {
   //提示用户没有权限
}

//检查用户是否具有某项权限
if (currentUser.isPermitted("user:edit")) {
   //执行用户编辑操作
} else {
   //提示用户没有权限
}

问题3:会话管理问题

问题原因: 可能是会话已经过期或者被踢出,也可能是会话配置出现问题。

解决办法: 检查会话配置是否正确,并确保会话状态可以正常保存和更新。如果需要增强会话管理功能,可以在代码中使用Shiro提供的会话管理API来实现。

代码示例:

//获取当前用户的会话
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();

//设置会话属性
session.setAttribute("key", "value");

//获取会话属性
Object value = session.getAttribute("key");

//使会话过期
session.setTimeout(1000);

//判断会话是否过期
if (session.isExpired()) {
   //提示用户会话已过期
} else {
   //执行操作
}

整合SpringBoot

步骤:

1. 新建Spring Boot项目,在pom.xml中引入相关的Shiro和Spring Boot Starter依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 创建Shiro配置类和Realm类:

Shiro配置类用于对Shiro进行配置,包括设置Realm、加密方式等,代码如下:

@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm() {
        return new MyRealm();
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm());
        return securityManager;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/login", "anon");
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

Realm类用于存储用户信息和鉴权操作。示例代码如下:

public class MyRealm extends AuthorizingRealm {

    private UserService userService;

    public MyRealm(UserService userService) {
        this.userService = userService;
        this.setCredentialsMatcher(new HashedCredentialsMatcher("SHA-256"));
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        String username = (String) token.getPrincipal();
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("User not exist");
        }
        Object credentials = user.getPassword();
        String realmName = getName();
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, credentials, realmName);
        return info;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        User user = (User) principals.getPrimaryPrincipal();
        List<Role> roles = userService.findRolesByUsername(user.getUsername());
        List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
        info.addRoles(roleNames);
        List<Permission> permissions = userService.findPermissionsByUsername(user.getUsername());
        List<String> permissionNames = permissions.stream().map(Permission::getName).collect(Collectors.toList());
        info.addStringPermissions(permissionNames);
        return info;
    }
}

3. 编写Controller类测试Shiro是否成功集成:

@RestController
public class UserController {

    @GetMapping("/login")
    public String login() {
        return "Please Login";
    }

    @GetMapping("/user")
    public String getUser() {
        return "Welcome, User";
    }

    @GetMapping("/admin")
    public String getAdmin() {
        return "Welcome, Admin";
    }
}

完整的示例代码:

ShiroConfig.java

@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm() {
        return new MyRealm();
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm());
        return securityManager;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/login", "anon");
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

MyRealm.java

public class MyRealm extends AuthorizingRealm {

    private UserService userService;

    public MyRealm(UserService userService) {
        this.userService = userService;
        this.setCredentialsMatcher(new HashedCredentialsMatcher("SHA-256"));
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        String username = (String) token.getPrincipal();
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("User not exist");
        }
        Object credentials = user.getPassword();
        String realmName = getName();
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, credentials, realmName);
        return info;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        User user = (User) principals.getPrimaryPrincipal();
        List<Role> roles = userService.findRolesByUsername(user.getUsername());
        List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
        info.addRoles(roleNames);
        List<Permission> permissions = userService.findPermissionsByUsername(user.getUsername());
        List<String> permissionNames = permissions.stream().map(Permission::getName).collect(Collectors.toList());
        info.addStringPermissions(permissionNames);
        return info;
    }
}

UserController.java

@RestController
public class UserController {

    @GetMapping("/login")
    public String login() {
        return "Please Login";
    }

    @GetMapping("/user")
    public String getUser() {
        return "Welcome, User";
    }

    @GetMapping("/admin")
    public String getAdmin() {
        return "Welcome, Admin";
    }
}
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: Apache Shiro java 安全框架
最后更新:2023年 5月 7日

墨风如雪

一个热爱生活,热爱分享的程序员

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

墨风如雪

一个热爱生活,热爱分享的程序员

最新 热点 随机
最新 热点 随机
告别机械感!OpenAudio S1让AI声音活起来 Sora触手可及!微软必应AI视频生成器,全民创作时代来临? 阿里WebAgent开源:引领自主搜索新纪元 重磅炸弹!字节跳动开源BAGEL:70亿参数,统一多模态理解与生成,AI“全能王”诞生记! 小米MiMo-VL:7B参数,怎么就成了多模态界的“越级打怪王”? 炸裂!DeepSeek 8B 量化版降临:告别显存焦虑,你的 3080 Ti 也能玩转顶级大模型了!
ComfyUI“打通任督二脉”:直接调用Veo2、GPT-4o等65大模型!一键串联你的AI工作流AI圈炸锅了!Mistral Medium 3:性能 SOTA,成本打骨折,企业玩家的新宠?字节终于开源“扣子”同款引擎了!FlowGram:AI 时代的可视化工作流利器告别“微信黑箱”!Chatlog:让你的聊天记录也能拥有“AI大脑”!字节跳动 Seed-Coder-8B:不靠人工洗数据,这80亿参数的小模型如何写出顶尖代码?85倍速的视觉革命:苹果发布 FastVLM,让你的 iPhone ‘看图说话’,快到飞起!
记录一次Ubuntu SSH报错问题的排查与解决 K8s 安装和部署详解 不再只是建议:Augment Agent 想成为真正帮你干活的 AI 开发伙伴! Swagger2用于API文档编写和测试的框架 RAGFlow深度解析:企业级开源知识引擎的部署实践与性能优化指南 探索AI编程的边界:GPT、Gemini、DeepSeek三巨头过招,谁能更胜一筹?
标签聚合
AI java spring deepseek 动态规划 教程 设计模式 算法

COPYRIGHT © 2023 墨风如雪博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

免责声明 - 隐私政策