一、引入maven配置

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

二、建表

用户表、角色表、权限表、用户角色表、角色权限表。

用户表:

角色表:

权限表:news:* 表示有新闻的所有权限(包括增删改查),而news:add,只有新闻的新增权限。

用户角色表:用户拥有哪些角色。

角色权限表:角色拥有哪些权限。

三、自定义Realm

自定义realm主要用于用户的权限验证以及登录验证。

自定义realm继承AuthorizingRealm类,并重写doGetAuthorizationInfo和doGetAuthenticationInfo方法,doGetAuthorizationInfo方法主要校验用户的权限,即该用户拥有什么角色以及权限。doGetAuthenticationInfo用于校验登录验证,即用户的用户名或者密码是否正确。

/**
 * 类名 : shiro的Realm
 * 用法 :
 * 创建人 : shyroke
 * 时间:2018/12/12 17:29
 */
public class MyRealm extends AuthorizingRealm {     @Autowired
    private UserMapper userMapper;     @Autowired
    private PermissionMapper permissionMapper;     /**
     * 授权,即该用户拥有什么角色以及权限
     * 步骤:根据用户名获取角色以及权限,然后设置到验证信息类并返回。
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();         String userName = principalCollection.getPrimaryPrincipal().toString(); //        获取该用户的角色
        List<Role> roles = userMapper.getRolesByUserName(userName);
        Set<String> roleSets = new HashSet<>(); //        获取该用户的权限集
        List<Permission> permissions = new ArrayList<>();
        Set<String> permissoinSet = new HashSet<>();         //将List转为Set
        if(roles !=null && roles.size()>0){
            for(Role role:roles){
                roleSets.add(role.getName());
                permissions.addAll(permissionMapper.getPermissionByRoleId(role.getId()));
            }
        }         //将List转为Set
        if(permissions!=null & permissoinSet.size()>0){
            for(Permission p :permissions){
                permissoinSet.add(p.getName());
            }
        }         info.addRoles(roleSets);
        info.addStringPermissions(permissoinSet);         return info;
    }     /**
     * 认证,即用户账号密码是否正确
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        获取用户名和密码
        String userName = (String)token.getPrincipal();
        String passWord = new String((char[]) token.getCredentials()); //        根据用户名查找该用户
        User user =  userMapper.getUserByName(userName);         if(user == null){
            throw new UnknownAccountException("用户名不存在");
        }         if(!user.getPassword().equals(passWord)){
            throw new IncorrectCredentialsException("密码错误");
        }         SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getName(),user.getPassword(),getName());         return info;
    }
}

四、shiro配置类

/**
 * 类名 :shiro的核心配置类
 * 用法 :
 * 创建人 : shyroke
 * 时间:2018/12/14 15:20
 */
@Configuration
public class ShiroConfigration { //    设置自定义Realm
    @Bean
    public MyRealm myRealm(){
        return new MyRealm();
    } //    权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }     /**
     * 设置过滤条件和跳转条件
     * anon 不生效的原因:1、map的类型必须是LinkedHashMap 2、anon必须定义在authc之前
     *
     * @param securityManager
     * @return
     */
    @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
            ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
            factoryBean.setSecurityManager(securityManager); //            设置登录跳转
            factoryBean.setLoginUrl("/admin");
            factoryBean.setSuccessUrl("/admin/index");             //必须为LinkedHashMap 否则anon不生效
            Map<String,String> map = new LinkedHashMap<>();             //退出
            map.put("/admin/logout","logout");             //登录页面和登录验证不要拦截
            map.put("/admin/login.html","anon");
            map.put("/admin/tologin","anon");             //设置需要过滤的链接
            map.put("/admin/**","authc");             factoryBean.setFilterChainDefinitionMap(map);             return factoryBean;
        }     /**
     *  开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }     /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    } }

五、调用

代码如下,当调用Subject.login方法后,会调用自定义Realm的doGetAuthenticationInfo方法校验用户名密码是否正确,如果不正确则抛出对应异常,controller层捕获并处理异常。

AuthenticationToken usernamePasswordToken = new UsernamePasswordToken(user.getName(),user.getPassword());

Subject subject = SecurityUtils.getSubject();

try {
    subject.login(usernamePasswordToken);
}catch (UnknownAccountException ex) {
    logger.info("用户名错误!");
    return R.error("用户名错误!");
} catch (IncorrectCredentialsException ex) {
    logger.info("密码错误!");
    return R.error("密码错误!");
} catch (AuthenticationException ex) {
    logger.info(ex.getMessage());
    return R.error("系统错误,请查看日志");
} catch (Exception ex) {
    logger.info(ex.getMessage());
    return R.error("系统错误,请查看日志");
}

(十二)springboot中shiro的使用的更多相关文章

  1. (转)SpringMVC学习(十二)——SpringMVC中的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...

  2. OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa

    元数据最本质.最抽象的定义为:data about data (关于数据的数据).它是一种广泛存在的现象,在许多领域有其具体的定义和应用. JDBC中的元数据,有数据库元数据(DatabaseMeta ...

  3. SpringBoot中Shiro缓存使用Redis、Ehcache

    在SpringBoot中Shiro缓存使用Redis.Ehcache实现的两种方式实例 SpringBoot 中配置redis作为session 缓存器. 让shiro引用 本文是建立在你是使用这sh ...

  4. SpringBoot中Shiro使用Pac4j集成CAS认证

    SpringBoot中Shiro使用Pac4j集成CAS认证 Pac4j 简介 Pac4j与Shiro,Spring Security一样都是权限框架,并且提供了OAuth - SAML - CAS ...

  5. springboot系列(十)springboot整合shiro实现登录认证

    关于shiro的概念和知识本篇不做详细介绍,但是shiro的概念还是需要做做功课的要不无法理解它的运作原理就无法理解使用shiro: 本篇主要讲解如何使用shiro实现登录认证,下篇讲解使用shiro ...

  6. (十二)整合 Shiro 框架,实现用户权限管理

    整合 Shiro 框架,实现用户权限管理 1.Shiro简介 1.1 基础概念 1.2 核心角色 1.3 核心理念 2.SpringBoot整合Shiro 2.1 核心依赖 2.2 Shiro核心配置 ...

  7. [十二]SpringBoot 之 servlet

    Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet.Filter.Listener.Interceptor 等等. 当使用spring-Boot时,嵌 ...

  8. 十二.spring-boot使用spring-boot-freemarker

    ①.在springMVC中:它代表着view层组件 ②.为什么使用freemarker:简单容易学.逻辑分明 ③.freemarker优点:它不依赖servlet.网络或者web环境 一.创建一个ma ...

  9. Expo大作战(十二)--expo中的自定义样式Custom font,以及expo中的路由Route&Navigation

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

随机推荐

  1. 缺jar包异常:java.lang.NoClassDefFoundError: org/springframework/core/convert/support/PropertyTypeDescriptor

    严重: StandardWrapper.Throwable java.lang.NoClassDefFoundError: org/springframework/core/convert/suppo ...

  2. 201671030120 王晶 实验十四 团队项目评审&课程学习总结

          项目 内容 课程名称 2016级计算机科学与工程学院软件工程(西北师范大学) 作业要求 实验十四 团队项目评审&课程学习总结 作业学习目标 (1)掌握软件项目评审会流程:(2)反思 ...

  3. destoon6.0调用公司设置任意信息的方法-最新

    destoon6.0调用公司设置任意信息的方法 用法: 把以下函数加入到api/extend.func.php 中 function company_setting($userid, $key = ' ...

  4. LOJ6070 基因

    基因 给定一个长度为 \(n\) 的字符串 \(s\),有 \(q\) 组询问,每个询问给定 \(l,r\),询问 \(s[l..r]\) 中有多少本质不同的回文子串. 强制在线.\(n\leq 10 ...

  5. Java Polymorphism

    Ability of an organism to take different shapes is polymorphism in bio world. A simplest definition ...

  6. python语言(四)关键字参数、内置函数、导入第三方模块、OS模块、时间模块

    一.可变参数 定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以).此时,可用包裹(packing)位置参数(*args),或者包裹关键字参数(**kwargs),来进行参数传递,会 ...

  7. Eclipse中将java类打成jar包形式运行

    记录一次帮助小伙伴将java类打成jar包运行 1.创建java project项目 file > new > project > java project 随便起一个项目名称,fi ...

  8. where与having 的区别

    二者的区别在于作用对象不同. where子句作用于基本表或视图,从中选择满足条件的一行或多行元祖. having短语作用于组,从中选择满足条件的组.这些组应该由group by 短句来进行分组.

  9. 工作拾记 - 关于easyui模板后台改为vue-element

    图1: 数据接口,模拟实现一些基本的数据条目 图2: 获取数据,接口都在src/api中 TODO LIST: 接下来要做的呢: 1. 完善此demo,基本的CURD,现在只有getAll,需要将增加 ...

  10. Reactive Extensions (Rx) 入门(5) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7749907 原文:http://www.atmarkit.co.jp/fdotnet/int ...