基于springboot实现整合shiro实现登录认证以及授权过程解析

这篇文章主要介绍了基于springboot实现整合shiro实现登录认证以及授权过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1.添加shiro的依赖

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

2.先创建一个Realm

public class MyShiroRealm extends AuthorizingRealm {
  @Autowired
  private RoleService roleService;//角色模模块
  @Autowired
  private UserService userService;//用户模块
  @Autowired
  private PermissionService permissionService;//权限模块
  /**
   * 用户身份识别(登录")
   * @param authenticationToken
   * @return
   * @throws AuthenticationException
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    UsernamePasswordToken authToken = (UsernamePasswordToken) authenticationToken;
    // 获取用户输入的账号
    String userName = authToken.getUsername();
     //通过账号查找用户信息
    User user= userService.selectUserOne(userName);// 将账户名,密码,盐值,getName()实例化到SimpleAuthenticationInfo中交给Shiro来管理
    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                              user,
                              user.getPassWord(),
                                    //这里是设置的密码盐
                              ByteSource.Util.bytes(user.getSalt()),
                              getName());
    return authenticationInfo;
  }

  /**
   * 访问控制。比如某个用户是否具有某个操作的使用权限
   * @param principalCollection
   * @return
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    String userName = (String) principalCollection.getPrimaryPrincipal();
    if (userName == null) {
      log.error("授权失败,用户信息为空!!!");
      return null;
    }
    try {
      //获取用户角色集
      Set<String> listRole= roleService.findRoleByUsername(userName);
      simpleAuthorizationInfo.addRoles(listRole);
      //通过角色获取权限集
      for (String role : listRole) {
        Set<String> permission= permissionService.findPermissionByRole(role);
        simpleAuthorizationInfo.addStringPermissions(permission);
      }
      return simpleAuthorizationInfo;
    } catch (Exception e) {
      log.error("授权失败,请检查系统内部错误!!!", e);
    }
    return simpleAuthorizationInfo;
  }
}

3.创建shiro的配置类

@Configuration
public class ShiroConfiguration {
   //配置自定义的Realm
  @Bean
  public MyShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){
    MyShiroRealm myShiroRealm= new MyShiroRealm();
     //在这里配置密码加密
    myShiroRealm.setCredentialsMatcher(matcher);
    return myShiroRealm;
  }

   //将Realm注册到securityManager中
  @Bean
  public DefaultWebSecurityManager securityManager(HashedCredentialsMatcher matcher){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(myShiroRealm(matcher));
    return securityManager;
  }

  //如果没有此name,将会找不到shiroFilter的Bean
  @Bean(name = "shiroFilter")
  public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager){
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    shiroFilterFactoryBean.setLoginUrl("/login");     //表示指定登录页面
    shiroFilterFactoryBean.setSuccessUrl("/user/list");  // 登录成功后要跳转的链接
    shiroFilterFactoryBean.setUnauthorizedUrl("/403");  //未授权页面

    Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//拦截器, 配置不会被拦截的链接 顺序判断
    filterChainDefinitionMap.put("/login","anon");           //所有匿名用户均可访问到Controller层的该方法下
    filterChainDefinitionMap.put("/userLogin","anon");
    filterChainDefinitionMap.put("/image/**","anon");
    filterChainDefinitionMap.put("/css/**", "anon");
    filterChainDefinitionMap.put("/fonts/**","anon");
    filterChainDefinitionMap.put("/js/**","anon");
    filterChainDefinitionMap.put("/logout","logout");
    filterChainDefinitionMap.put("/**", "authc"); //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
    //filterChainDefinitionMap.put("/**", "user");    //user表示配置记住我或认证通过可以访问的地址
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  }

  /**
   * SpringShiroFilter首先注册到spring容器
   * 然后被包装成FilterRegistrationBean
   * 最后通过FilterRegistrationBean注册到servlet容器
   * @return
   */
  @Bean
  public FilterRegistrationBean delegatingFilterProxy(){
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    DelegatingFilterProxy proxy = new DelegatingFilterProxy();
    proxy.setTargetFilterLifecycle(true);
    proxy.setTargetBeanName("shiroFilter");
    filterRegistrationBean.setFilter(proxy);
    return filterRegistrationBean;
  }
  //设置cookie
  @Bean
  public SimpleCookie rememberMeCookie(){
    //这个参数是cookie的名称,对应前端的checkbox的name=rememberMe
    SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
    //记住我cookie生效时间3个小时(单位秒)
    simpleCookie.setMaxAge(10800);
    return simpleCookie;
  }
  //cookie管理对象,记住我功能
  @Bean
  public CookieRememberMeManager rememberMeManager(){
    CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
    cookieRememberMeManager.setCookie(rememberMeCookie());
    return cookieRememberMeManager;
  }
  /**
   * 密码匹配凭证管理器(密码加密需要此配置)
   * @return
   */
  @Bean(name = "hashedCredentialsMatcher")
  public HashedCredentialsMatcher hashedCredentialsMatcher() {
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName("MD5");
    hashedCredentialsMatcher.setHashIterations(1024);// 设置加密次数
    return hashedCredentialsMatcher;
  }
  //如果没有这两个配置,可能会授权失败,所以依赖中还需要配置aop的依赖
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(HashedCredentialsMatcher matcher) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager(matcher));
    return authorizationAttributeSourceAdvisor;
  }
  @Bean
  @ConditionalOnMissingBean
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
  }
}

4.新建controller并写个登录的方法

/**
   * 登录页面 这里对应shiro中配置的shiroFilter的登录方法
   * @return
   */
  @GetMapping("/login")
  public String login() {
    return "user/login";
  }
//登录方法
  @PostMapping("/userLogin")
  public String toLogin( String userName,String passWord,Model model){
    UsernamePasswordToken token =new UsernamePasswordToken(userName,passWord);
    Subject subject = SecurityUtils.getSubject();
    try {
      //这里直接使用shiro的登录方法
      subject.login(token);
      return "redirect:user/list";
     //登录失败时,会catch到你的异常,异常通过全局处理
    } catch (UnknownAccountException e) {
      model.addAttribute("msg","该账号不存在");
    } catch (IncorrectCredentialsException e) {
      model.addAttribute("msg","密码错误,请重试");
    } catch (LockedAccountException e) {
      model.addAttribute("msg","该账户已被锁定,请联系管理员");
    } catch (Exception e) {
      model.addAttribute("msg","登录失败");
    }
    return "user/login";
  }
//添加
@RequestMapping("/insertUser")
@ResponseBody
public int insertUser(User user){
  //将uuid设置为密码盐值
  String salt = UUID.randomUUID().toString().replaceAll("-","");
  SimpleHash simpleHash = new SimpleHash("MD5", user.getPassWord(), salt, 1024);
   //添加用户信息
  user.setPassWord(simpleHash.toHex()).setValid(1).setSalt(salt).setCreateTime(new Date()).setDel(0);
  return userMapper.insertSelective(user);
}

5.创建全局异常处理类

@RestControllerAdvice
public class GlobalExceptionHandle {
  @ExceptionHandler(ShiroException.class)
  public String doHandleShiroException(ShiroException se,Model model) {
    se.printStackTrace();
  if(se instanceof UnknownAccountException) return "账户不存在!";
  else if(se instanceof LockedAccountException) return "账户已锁定,请联系管理员";
  else if(se instanceof IncorrectCredentialsException) return "密码错误,请重试";
  else if(se instanceof AuthorizationException) return "没有相应权限,请联系管理员";
  else return "登录失败";
  }
}

权限需要开启权限注解才生效

@GetMapping("/userPageList")
  @ResponseBody
  @RequiresPermissions("user:view") //这里是用户对应的权限
  public PageList listPage(HttpServletRequest request){
    PageList pageList = new PageList();
    List<User> list= userService.findAllPage(request);//查询出的条数
    int totalCount = userService.countAll();//总记录数
    pageList.setRows(list);
    pageList.setTotal(totalCount);
    return pageList;
  }

shiro用户角色和权限表

-- Table structure for `sys_permission`
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
 `id` int(64) NOT NULL AUTO_INCREMENT,
 `name` varchar(32) DEFAULT NULL,
 `permission` varchar(32) DEFAULT NULL,
 `url` varchar(64) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_permission
-- ----------------------------
INSERT INTO `sys_permission` VALUES ('1', '用户管理', 'user:view', 'user/userPageList');
INSERT INTO `sys_permission` VALUES ('2', '用户添加', 'user:add', 'user/saveUser');
INSERT INTO `sys_permission` VALUES ('3', '用户删除', 'user:del', 'user/delById');

-- ----------------------------
-- Table structure for `sys_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
 `id` int(64) NOT NULL,
 `available` varchar(8) DEFAULT NULL,
 `description` varchar(32) DEFAULT NULL,
 `role` varchar(32) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '1', '管理员', 'admin');
INSERT INTO `sys_role` VALUES ('2', '1', 'VIP会员', 'vip');

-- ----------------------------
-- Table structure for `sys_role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
 `permission_id` int(64) NOT NULL COMMENT '权限表主键',
 `role_id` int(64) NOT NULL COMMENT '角色表主键'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role_permission
-- ----------------------------
INSERT INTO `sys_role_permission` VALUES ('1', '1');
INSERT INTO `sys_role_permission` VALUES ('2', '1');

-- ----------------------------
-- Table structure for `sys_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
 `role_id` int(64) NOT NULL,
 `user_id` int(64) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1');

-- ----------------------------
-- Table structure for `user_info`
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
 `id` int(64) NOT NULL AUTO_INCREMENT,
 `name` varchar(32) DEFAULT NULL,
 `password` varchar(64) DEFAULT NULL,
 `salt` varchar(64) DEFAULT NULL,
 `state` varchar(8) DEFAULT NULL,
 `username` varchar(32) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES ('1', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', '1', 'admin');

最后声明下!!!我的开发环境是windows10+JDK1.8+springboot2.1.7+shiro1.4.0

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot整合Shiro两种方式(总结)

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. <!--more--> 今天松哥就来和大家聊聊 Spring Boot 整合 Shiro 的话题! 一般来说,Spring Security 和 Shiro 的比较如下: Spring Security 是一个重量级的安全管理框架:Shiro 则是一个轻量级的安全管理框架 Spring Security 概念复杂,配置繁琐:Shiro 概念简单

  • springboot整合shiro登录失败次数限制功能的实现代码

    这次讲讲如何限制用户登录尝试次数,防止坏人多次尝试,恶意暴力破解密码的情况出现,要限制用户登录尝试次数,必然要对用户名密码验证失败做记录,Shiro中用户名密码的验证交给了CredentialsMatcher 所以在CredentialsMatcher里面检查,记录登录次数是最简单的做法.当登录失败次数达到限制,修改数据库中的状态字段,并返回前台错误信息.  因为之前的博客都是用的明文,这里就不对密码进行加密了,如果有需要加密,将自定义密码比较器从SimpleCredentialsMatcher

  • SpringBoot中Shiro缓存使用Redis、Ehcache的方法

    SpringBoot 中配置redis作为session 缓存器. 让shiro引用 本文是建立在你是使用这shiro基础之上的补充内容 第一种:Redis缓存,将数据存储到redis 并且开启session存入redis中. 引入pom <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifac

  • spring boot整合Shiro实现单点登录的示例代码

    Shiro是什么 Shiro是一个Java平台的开源权限框架,用于认证和访问授权.具体来说,满足对如下元素的支持: 用户,角色,权限(仅仅是操作权限,数据权限必须与业务需求紧密结合),资源(url). 用户分配角色,角色定义权限. 访问授权时支持角色或者权限,并且支持多级的权限定义. Q:对组的支持? A:shiro默认不支持对组设置权限. Q:是否可以满足对组进行角色分配的需求? A:扩展Realm,可以支持对组进行分配角色,其实就是给该组下的所有用户分配权限. Q:对数据权限的支持? 在业务

  • SpringBoot Shiro授权实现过程解析

    这篇文章主要介绍了SpringBoot Shiro授权实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用Shiro过滤器实现授权 设置好授权拦截跳转的请求地址 /** * 创建ShiroFilterFactoryBean */ @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") Defaul

  • Springboot整合Shiro之加盐MD5加密的方法

    1.自定义realm,在Shiro的配置类中加入以下bean /** * 身份认证 realm */ @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); System.out.println("myShiroRealm 注入成功"); return myShiroRealm; } 2.重写方法 // 身份认证 @Override protected Authe

  • spring boot整合shiro安全框架过程解析

    这篇文章主要介绍了spring boot整合shiro安全框架过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 题记:在学习了springboot和thymeleaf之后,想完成一个项目练练手,于是使用springboot+mybatis和thymeleaf完成一个博客系统,在完成的过程中出现的一些问题,将这些问题记录下来,作为自己的学习心得.在这先感谢群主TyCoding的Tumo项目,虽然本人实在太菜了,好些地方看不懂,但还是使我受益

  • SpringBoot + Shiro前后端分离权限

    shiro 验证通过后的信息保存在session 中,而ajax 每次传的都是不同的sessionid ,所以主要的区别就是需要修改shiro获取sessionid的方式.这里使用的是登录后将后台的sessionid 传到前端然后存放到 cookie(这个存放的地方视情况而定),然后每次请求后端时在Header中携带此信息,这里起名为Authorization shiro 中 默认获取Sessionid的类是 DefaultWebSessionManager 所以需要重写此类 import or

  • 基于springboot实现整合shiro实现登录认证以及授权过程解析

    这篇文章主要介绍了基于springboot实现整合shiro实现登录认证以及授权过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.添加shiro的依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web- starter</artifactId> <version&g

  • SpringBoot整合Shiro实现登录认证的方法

    安全无处不在,趁着放假读了一下 Shiro 文档,并记录一下 Shiro 整合 Spring Boot 在数据库中根据角色控制访问权限 简介 Apache Shiro是一个功能强大.灵活的,开源的安全框架.它可以干净利落地处理身份验证.授权.企业会话管理和加密. 上图是 Shiro 的基本架构 Authentication(认证) 有时被称为"登录",用来证明用户是用户他们自己本人 Authorization(授权) 访问控制的过程,即确定"谁"访问"什么

  • SpringBoot 整合 Shiro 密码登录与邮件验证码登录功能(多 Realm 认证)

    导入依赖(pom.xml) <!--整合Shiro安全框架--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <!--集成jwt实现token认证--> <dependency

  • SpringBoot 整合 Shiro 密码登录的实现代码

    导入依赖(pom.xml) <!--整合Shiro安全框架--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <!--集成jwt实现token认证--> <dependency

  • springboot整合shiro实现登录验证授权的过程解析

    springboot整合shiro实现登录验证授权,内容如下所示: 1.添加依赖: <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.7.1</version> </dependency> 2.yml配置: #配置服务端口 s

  • Springboot整合Shiro实现登录与权限校验详细解读

    目录 Springboot-cli 开发脚手架系列 简介 前言 1. 环境 2. 简介 3. Realm配置 4. 核心配置 5. 接口编写 6. 网页资源 7. 效果演示 8. 源码分享 Springboot-cli 开发脚手架系列 Springboot优雅的整合Shiro进行登录校验,权限认证(附源码下载) 简介 Springboo配置Shiro进行登录校验,权限认证,附demo演示. 前言 我们致力于让开发者快速搭建基础环境并让应用跑起来,提供使用示例供使用者参考,让初学者快速上手. 本博

  • SpringBoot整合Sa-Token实现登录认证的示例代码

    目录 依赖 登录 退出登录 前后端分离 今天分享的是 Spring Boot 整合 Sa-Token 实现登录认证. 依赖 首先,我们需要添加依赖: 关键依赖: <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.28.0</version> </depend

  • SpringBoot整合token实现登录认证的示例代码

    1.pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</group

  • SpringBoot中整合Shiro实现权限管理的示例代码

    之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧 一.简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序. 三个核心组件: 1.Subject 即"当前操作用户".但是,在 Shi

  • java编程之基于SpringBoot框架实现扫码登录

    目录 项目简介 实现思路 二次认证的原因 实现步骤 用户访问网页端,选择扫码登录 使用手机扫码,二维码状态改变 手机确认登录 效果演示 完整代码已上传到GitHub. Web端体验地址:http://47.116.72.33/(只剩一个月有效期) apk下载地址:https://github.com/zhangjiwei1221/qrscan/releases/tag/0.0.1. 用户名:非空即可,密码:123456,效果见文末,整体实现如有不妥之处,欢迎交流讨论 实现部分参考二维码扫码登录是

随机推荐