跟着我的步骤:先运行起来再说

Spring集成Shiro的GitHub:https://github.com/yueshutong/shiro-imooc


一:导包

        <!-- Shiro安全框架 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

二:ShiroConfig配置


import cn.zyzpp.shiro.CustomRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Create by yster@foxmail.com 2018/5/17/017 20:18
 */
@Configuration
public class ShiroConfig {
    /**
     * 记住我:自动登录-1
     */
    @Bean
    public SimpleCookie getSimpleCookie(){
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName("rememberMe");
        simpleCookie.setMaxAge(20000000);
        return simpleCookie;
    }

    /**
     * 记住我:自动登录-2
     */
    @Bean
    public CookieRememberMeManager getCookieRememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(getSimpleCookie());
        return cookieRememberMeManager;
    }

    /**
     * 开启MD5加密
     * @return
     */
    @Bean
    public HashedCredentialsMatcher getMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(1);
        return matcher;
    }

    /**
     * 自定义Realm密码验证与加密
     * @return
     */
    @Bean
    public CustomRealm getCustomRealm(){
      CustomRealm customRealm = new CustomRealm();
      customRealm.setCredentialsMatcher(getMatcher());
      return customRealm;
    }

    /**
     * 创建SecurityManager环境
     * @return
     */
    @Bean
    public DefaultWebSecurityManager getSecurityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(getCustomRealm());
        securityManager.setRememberMeManager(getCookieRememberMeManager());
        return securityManager;
    }

    /**
     * Shiro在Web项目中的过滤
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getfilterFactoryBean(){
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(getSecurityManager());
        /**
         *  只有在下面配置路径访问权限,Shiro才会执行自动跳转。
         *  如果使用Shiro注解权限,就只会报异常,
         *  就只能采用统一异常处理的方法。
         */
        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/static/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/user/exit", "logout");
        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/user/user", "authc");
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        filterFactoryBean.setLoginUrl("/user/login");
        // 登录成功后要跳转的链接
        filterFactoryBean.setSuccessUrl("/");
        //未授权界面;
        filterFactoryBean.setUnauthorizedUrl("/user/login");
        filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return filterFactoryBean;
    }

    /**
     * 保证Shiro的声明周期
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启Shiro授权生效
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        return new AuthorizationAttributeSourceAdvisor();
    }

}

三:自定义授权类

import cn.zyzpp.service.user.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.Set;

/**
 * Create by yster@foxmail.com 2018/5/17/017 20:38
 */
public class CustomRealm extends AuthorizingRealm {

    private String ClassName =this.getClass().getName();

    @Autowired
    @Lazy   //必须懒加载,否则Ehcache缓存注解及事务管理注解无效
    private UserService userService;

    {
        super.setName(ClassName);
    }

    /**
     * 权限处理
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        // 从数据库或者缓存中获得角色数据
        Set<String> roles = userService.getRolesByUserName(username);
        Set<String> permissions = userService.getPermissionsByRoles(roles);
        //上面的service层方法需要自己写
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setStringPermissions(permissions);
        simpleAuthorizationInfo.setRoles(roles);

        return simpleAuthorizationInfo;
    }

    /**
     * 认证处理
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1.从主体传过来的认证信息中,获得用户名
        String username = (String) token.getPrincipal();

        // 2.通过用户名到数据库中获取凭证
        String password = userService.getPasswordByUsername(username);
        if(password == null) {
            return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, ClassName);
        return simpleAuthenticationInfo;
    }

}

四:使用

1)登录验证:

    @RequestMapping(value = "/login/result", method = RequestMethod.POST)
    public String userLogin(User user) {
        String error = null;
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getMail(), user.getPassword());
        try {
            token.setRememberMe(user.isRememberMe());//记住我
            subject.login(token);
        } catch (UnknownAccountException e) {
            error = "用户名/密码错误";
        } catch (IncorrectCredentialsException e) {
            error = "用户名/密码错误";
        } catch (AuthenticationException e) {
            //其他错误,比如锁定,如果想单独处理请单独catch处理
            error = "其他错误:" + e.getMessage();
        }
        if(error != null) {//出错了,返回登录页面

        } else {//登录成功

        }
    }

2)权限验证:

  • 可以在配置文件中配置Url权限等,参考步骤二。

  • 使用诸如 @RequiresRoles(“user”) 注解在controller层的方法上,进行角色验证,或者使用@RequiresPermissions(“index:hello”)进行权限验证,不过使用注解Shiro就只抛出异常,无法使用shiro设置自动跳转到页面等。针对这个问题,可以用@ControllerAdvice统一异常处理。

    @RequiresRoles("user")
    @RequestMapping(value = "/up")
    public String up(){

    }

本实例旨在讲解SpringBoot集成,Shiro教程推荐:http://wiki.jikexueyuan.com/project/shiro/

SpringBoot集成Shiro安全框架的更多相关文章

  1. SpringBoot学习笔记(五):SpringBoot集成lombok工具、SpringBoot集成Shiro安全框架

    SpringBoot集成lombok工具 什么是lombok? 自动生成setget方法,构造函数,打印日志 官网:http://projectlombok.org/features/index. 平 ...

  2. 在前后端分离的SpringBoot项目中集成Shiro权限框架

    参考[1].在前后端分离的SpringBoot项目中集成Shiro权限框架 参考[2]. Springboot + Vue + shiro 实现前后端分离.权限控制   以及跨域的问题也有涉及

  3. SpringBoot集成Shiro并用MongoDB做Session存储

    之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...

  4. springboot集成shiro实现权限认证

    github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...

  5. Springboot整合Shiro安全框架

    最近在学习Springboot,在这个过程中遇到了很多之前都没有技术知识,学习了一阵子,稍微总结一些. ---- Shiro框架 shiro框架,是一个相对比较简便的安全框架,它可以干净利落地处理身份 ...

  6. SpringBoot集成Shiro 实现动态加载权限

    一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...

  7. springboot集成shiro 实现权限控制(转)

    shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...

  8. SpringBoot集成Shiro实现权限控制

    Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...

  9. 【Shiro】SpringBoot集成Shiro

    项目版本: springboot2.x shiro:1.3.2 Maven配置: <dependency> <groupId>org.apache.shiro</grou ...

随机推荐

  1. Java虚拟机(四)垃圾收集算法

    前言 在本系列上一篇文章中我讲到了垃圾标记算法,垃圾被标记后,GC就会对垃圾进行收集,垃圾收集有很多种算法,这篇文章就来介绍常用的垃圾收集算法的思想. 1.标记-清除算法 标记-清除算法(Mark-S ...

  2. Android--记录莫名其妙的引用、依赖冲突解决办法

    这几天一直在忙于其他项目,打开之前的项目,我曹,代码什么都没动,为何莫名其妙的的就出现冲突了.(我猜测是依赖的其它三方库,库里面的依赖发生改变导致的) 全是这种错误,各种冲突导致的,记录一下,以下指示 ...

  3. (网页)习惯了CS回车操作人员,操作BS网页表单也是回车666

    1.第一步把表单,里面需要回车的input,或者是其他的表单按钮给一个clsss,例如下面的$('.cls'); 2.第二步,  把下面的代码复制过去,填写完最后一个自动提交:$("#sav ...

  4. mac上Docker安装&初体验

    Docker是什么? Docker是一个虚拟环境容器,可以将你的开发环境.代码.配置文件等一并打包到这个容器中,并发布和应用到任意平台中. 官方文档:https://docs.docker.com H ...

  5. Android 弹出输入框

    final EditText inputServer = new EditText(SettingActivity.this); AlertDialog.Builder builder = new A ...

  6. HBase数据库相关基本知识

    HBase数据库相关知识 1. HBase相关概念模型 l  表(table),与关系型数据库一样就是有行和列的表 l  行(row),在表里数据按行存储.行由行键(rowkey)唯一标识,没有数据类 ...

  7. June 3. 2018 Week 23rd Sunday

    You only get one shot; do not miss your chance to blow. 机会只有一次,不要错过. From Eminem, "Lose Yoursel ...

  8. 【HNOI2013】切糕

    [HNOI2013]切糕 Sample Input 2 2 2 1 6 1 6 1 2 6 2 6 Sample Output 6 \(P,Q,R≤40,0≤D≤R\) 参考:https://blog ...

  9. WPF中应用字体图标

    一.什么是字体图标 我们在进行GDI(图形界面)编程的过程中图标是不可少的.近些年随着网络的繁荣和移动应用的繁荣,矢量图的应用越来越火. 矢量图是一种用数学方法描述的.由一系列点和线组成的图,因此相比 ...

  10. 经常在比特币中看到的merkle树是什么?

    区块基础-merkle树   Merkle tree中文叫做梅克尔树,这当然不是一棵真正的植物树,merkle tree是计算机数据结构中的一种树,是由计算机科学家 Ralph Merkle 提出的, ...