Spring Boot Shiro在Web应用中的作用详解

Spring Boot Shiro在Web应用中的作用详解

简介

Spring Boot Shiro是基于Spring Boot和Shiro的安全管理框架,可以方便地集成到Web应用中。它提供了一种简单、灵活且强大的身份验证和授权机制,可以在应用中实现多种安全需求,并且易于扩展和定制。

快速开始

依赖

在您的pom.xml文件中添加Spring Boot Shiro的依赖:

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

配置

在application.yml中添加shiro相关的配置:

# shiro
shiro:
  # 登录url
  loginUrl: /login
  # 成功后跳转的url
  successUrl: /index
  # 未授权url
  unauthorizedUrl: /403
  # 登出url
  logoutUrl: /logout
  # shiro加密方式
  hashAlgorithmName: md5
  # hash次数
  hashIterations: 1024
  # 是否开启记住我
  rememberMe: true
  cookie:
    # cookie名称
    name: rememberMe
    # cookie过期时间
    maxAge: 604800
    # cookie加密密钥
    cipherKey: 8AvVhmFLUs0KTA3Kprsdag==

# Shiro 配置
shiro:
  # ShiroFilter 配置
  filter:
    # 设置默认过滤器,顺序有讲究,细节请看文档,登陆成功主要看user这个拦截器
    loginUrl: /login
    unauthorizedUrl: /403
    anon: anon
    user: user
    logout: logout

  # ShiroRealm 配置
  realm:
    # 自定义的Realm类
    class-name: com.test.realm.UserRealm
    # 加密方式
    credentialsMatcher:
      hashAlgorithmName: MD5
      hashIterations: 1024

实现UserRealm

自定义UserRealm需要继承Shiro的AuthorizingRealm类,并实现doGetAuthorizationInfo()和doGetAuthenticationInfo()方法。其中,doGetAuthorizationInfo()用于获取授权信息,doGetAuthenticationInfo()用于获取身份验证信息。

以下是一个示例:

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    // 获取授权信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 
        //获取登录用户名
        String username= (String) principalCollection.getPrimaryPrincipal();
        // 根据用户名查询该用户的角色和权限
        User user = userService.findByUserName(username);
        Set<String> roles = new HashSet<>();
        roles.add(user.getRole());
        authorizationInfo.setRoles(roles);
        Set<String> permissions = new HashSet<>();
        permissions.add(user.getPermissions());
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    // 获取身份验证信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        String username = token.getUsername();
        User user = userService.findByUserName(username);
        if(user == null){
            throw new UnknownAccountException("用户名或密码错误!");
        }
        return new SimpleAuthenticationInfo(username,user.getPassword(),getName());
    }
}

实现登录、登出、授权

在controller中添加对应的方法来实现登录、授权、登出等功能。以下是一个示例:

@RestController
public class UserController {

    // 用户登录
    @PostMapping("/login")
    public Result login(@RequestParam String username,
                           @RequestParam String password,
                           @RequestParam(defaultValue = "false") Boolean rememberMe){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,password,rememberMe);
        try{
            subject.login(token);
            User user = (User)subject.getPrincipal();
            return Result.success("登录成功!", user);
        }catch (UnknownAccountException e){
            throw new UnknownAccountException("用户名或密码错误!");
        }catch (IncorrectCredentialsException e){
            return Result.error("用户名或密码错误!");
        }
    }

    // 用户登出
    @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "redirect:/login";
    }

    // 用户授权
    @GetMapping("/index")
    @RequiresPermissions("user:index")
    public String index(){
        return "index";
    }
}

示例

示例一:基于注解的权限控制

@RestController
public class UserController {

    // 用户首页
    @GetMapping("/index")
    @RequiresPermissions("user:index")
    public String index(){
        return "This is index page.";
    }

    // 用户列表
    @GetMapping("/user/list")
    @RequiresPermissions("user:list")
    public String list(){
        return "This is user list page.";
    }

    // 用户编辑
    @GetMapping("/user/edit")
    @RequiresPermissions("user:edit")
    public String edit(){
        return "This is user edit page.";
    }

    // 用户删除
    @GetMapping("/user/delete")
    @RequiresPermissions("user:delete")
    public String delete(){
        return "This is user delete page.";
    }
}

该示例中,使用@RequiresPermissions注解定义访问该方法需要的权限。当用户没有该权限时,访问该方法会返回403错误页面。

示例二:记住我功能和退出登录

@RestController
public class UserController {

    // 用户列表
    @GetMapping("/user/list")
    @RequiresPermissions("user:list")
    public String list(){
        return "This is user list page.";
    }

    // 用户首页
    @GetMapping("/index")
    @RequiresPermissions("user:index")
    public String index(){
        return "This is index page.";
    }

    // 用户登录
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@RequestParam String username,
                           @RequestParam String password,
                           @RequestParam(defaultValue = "false") Boolean rememberMe,
                           HttpServletRequest request){
        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(rememberMe);
        try{
            currentUser.login(token);
            User user = (User) currentUser.getPrincipal();
            request.getSession().setAttribute("user", user);
            return "redirect:/index";
        } catch (UnknownAccountException uae) {
            return "用户名不存在";
        } catch (IncorrectCredentialsException ice) {
            return "密码不正确";
        }
    }

    // 退出登录
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request){
        SecurityUtils.getSubject().logout(); //完成退出
        request.getSession().invalidate();
        return "redirect:/login";
    }

}

该示例中,使用HttpServletRequest来获取Session,并将登录用户信息保存到Session中,以便实现记住我功能。同时,当用户点击退出登录时,使用SecurityUtils.getSubject().logout()方法来完成退出操作,并清除Session。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot Shiro在Web应用中的作用详解 - Python技术站

(0)
上一篇 2023年6月2日
下一篇 2023年6月2日

相关文章

  • Java的split方法使用详解

    Java的split方法使用详解 简介 Java中的String类提供了许多操作字符串的方法,其中split()方法是一个非常实用的方法。split()方法的作用是将字符串按照指定的分隔符分解成多个子字符串,返回的是一个字符串数组。本文将详细讲解split()方法的使用。 语法 split()方法的语法如下: public String[] split(St…

    Java 2023年5月27日
    00
  • java 中的乱码问题汇总及解决方案

    Java 中的乱码问题汇总及解决方案 在 Java 中,由于字符集编码不统一或者操作过程中出现错误,会导致乱码问题的出现。以下是解决 Java 中乱码问题的一些方法总结。 字符集编码不正确 确定并设置编码方式 在 Java 的编码过程中,需要使用字符集编码,否则会出现乱码。在开发中,一般使用 UTF-8 编码,若使用其他编码方式,需要明确指定字符集编码。比如…

    Java 2023年5月19日
    00
  • Java语言中的文件数据流示例详解

    Java语言中的文件数据流是用于读写文件的常用方法之一,主要用于在Java程序中读取文件内容或将程序中生成的数据写入文件中。下面就对Java语言中的文件数据流进行详细讲解,包含过程中的两条示例。 一、文件数据流的概述 1.1 数据流的概念 数据流是指一种按照一定规则流动的数据,就像水流一样。在Java中,数据流是一种用于读写数据的对象,通常用于读写文件或网络…

    Java 2023年5月20日
    00
  • SpringBoot实现在webapp下直接访问html,jsp

    下面详细讲解如何在SpringBoot中配置,使得可以在webapp目录下直接访问HTML、JSP等静态资源。 1. Maven依赖 在pom.xml文件中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>s…

    Java 2023年5月20日
    00
  • Springboot通过配置WebMvcConfig处理Cors非同源访问跨域问题

    下面是详细的讲解。 什么是跨域? 跨域是指在浏览器的同源策略下,一个页面的脚本(包括JavaScript、Ajax等)访问另一个页面的数据时,出现了协议、域名或端口号不同的情况。如果不做任何处理,浏览器会阻止跨域请求,会产生“跨域问题”。 跨域解决方案 在前后端分离的项目中,开发人员经常会遇到跨域问题。解决跨域问题的方法很多,其中一种是使用CORS(跨域资源…

    Java 2023年5月23日
    00
  • SpringBoot详细介绍SPI机制示例

    SpringBoot详细介绍SPI机制示例 在SpringBoot中,我们可以使用SPI机制来扩展框架的功能。本文将详细讲解SpringBoot详细介绍SPI机制示例的完整攻略,并提供两个示例。 1. SPI机制 SPI全称为Service Provider Interface,是Java提供的一种服务发现机制。在SPI机制中,服务提供者提供一种服务接口,而…

    Java 2023年5月15日
    00
  • java小程序火锅店点餐系统

    Java小程序火锅店点餐系统攻略 1. 介绍 Java小程序火锅店点餐系统是一款基于Java语言和微信小程序开发的点餐系统。它具有用户注册、食品浏览、食品加入购物车、下单支付、交易查询等功能。通过小程序界面实现了用户的选购与交易过程,为用户提供了便捷的外卖服务。 2. 技术要点 前端框架:使用微信小程序原生组件和wxParse富文本解析插件,使界面风格简洁美…

    Java 2023年5月23日
    00
  • 超级全面的PHP面试题整理集合

    下面是详细的“超级全面的PHP面试题整理集合”的攻略: 了解题目类型 首先,我们需要了解常见的PHP面试题目类型,包括基础知识、算法题、框架相关、数据库相关等。通过了解这些题目类型,我们可以对备考做出有针对性的准备。 例如,对于基础知识题目,需要掌握变量、语法规则、函数等基本知识,同时还需要注意PHP的底层实现原理;对于算法题目,需要熟练掌握各类排序、查找、…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部