一、引入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. cmds在线重定义增加列

    --输出信息采用缩排或换行格式化 EXEC DBMS_METADATA.set_transform_param(DBMS_METADATA.session_transform, 'PRETTY', T ...

  2. JSR303后端校验(一)

    JSR303后端校验(一) (1)在pom文件中添加依赖 <!-- JSR303后端校验 --> <dependency> <groupId>org.hiberna ...

  3. sparkjob的提交流程

    在使用spark-submit提交一个Spark应用之后,Driver程序会向集群申请一定的资源来启动东若干个Executors用来计算,当这些Executors启动后,它们会向Driver端的Sch ...

  4. Worldview in Context

    Worldview in Context Figures 1 and 2 provide a basis for a deeper understanding of worldview. The se ...

  5. (3)使用Android手机作为树莓派的屏幕

    https://jingyan.baidu.com/album/676629977483b154d51b848e.html

  6. [Algorithm] 283. Move Zeroes

    Given an array nums, write a function to move all 0's to the end of it while maintaining the relativ ...

  7. Numpy | 07 从数值范围创建数组

    numpy.arange ***** 使用numpy 包中的 arange 函数,创建数值范围并返回 ndarray 对象,函数格式如下: numpy.arange(start, stop, step ...

  8. system.stat[resource,<type>]

    系统信息. 整型或者浮点型 ent - 该分区有权接收的处理器单元数(float) kthr, - 关于内核线程状态的信息: r - 平均可运行内核线程数(float) b - 虚拟内存管理器等待队列 ...

  9. A@GC*014

    A@GC*014 A Cookie Exchanges 卡时跑了1s就输出-1 每次操作会使三个数的极差缩小一半,所以最多\(\log\)次之后就会出现\(A=B=C\)的情况,可以直接判掉 B Un ...

  10. [后渗透]Windows server 80端口复用后门

    0x01 简介 该后门的基本原理是使用Windows 的远程管理管理服务WinRM,组合HTTP.sys驱动自带的端口复用功能,一起实现正向的端口复用后门. 具体细节信息请参考:https://pap ...