文章目录

  • 1.shiro依赖
  • 2.shiro配置
    • shiro过滤器配置:
    • 关联自定义的其他管理器
    • 自定义会话工厂:
  • 3.登陆时记录用户信息
  • 4.shiro一些工具类的学习
  • 5.自定义登录拦截器

shiro是一个安全框架,用于认证和授权,我觉得与springsecurity相比它上手更容易,同时如果是简单的登录拦截也可以用登录拦截器实现,下面先进行springboot整合 shiro的过程

1.shiro依赖

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

2.shiro配置

配置安全管理器:SecurityManager
Authenticator 的职责是验证用户帐号,是ShiroAPI 中身份验证核心的入口点:如果验证成功,将返回AuthenticationInfo验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的AuthenticationException异常
•SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm 进行验证,验证规则通过AuthenticationStrategy接口指定

  /*** 安全管理器*/@Beanpublic SecurityManager securityManager(UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 设置realm.securityManager.setRealm(userRealm);// 记住我securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);// 注入缓存管理器;securityManager.setCacheManager(getEhCacheManager());// session管理器securityManager.setSessionManager(sessionManager());return securityManager;}

哪些url是需要拦截的,哪些是不需要拦截的,登录页面、登录成功页面的url、自定义的Realm等这些信息需要设置到Shiro中

shiro过滤器配置:

 /*** Shiro过滤器配置*/@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// Shiro的核心安全接口,这个属性是必须的shiroFilterFactoryBean.setSecurityManager(securityManager);// 身份认证失败,则跳转到登录页面的配置shiroFilterFactoryBean.setLoginUrl(loginUrl);// 权限认证失败,则跳转到指定页面shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);// Shiro连接约束配置,即过滤链的定义LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// 对静态资源设置匿名访问filterChainDefinitionMap.put("/favicon.ico**", "anon");//加入自己的路径和访问权限// 系统权限列表// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());Map<String, Filter> filters = new LinkedHashMap<String, Filter>();filters.put("onlineSession", onlineSessionFilter());filters.put("syncOnlineSession", syncOnlineSessionFilter());filters.put("captchaValidate", captchaValidateFilter());filters.put("kickout", kickoutSessionFilter());// 注销成功,则跳转到指定页面filters.put("logout", logoutFilter());shiroFilterFactoryBean.setFilters(filters);// 所有请求需要认证filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}

安全管理器关联自己的Realm

  @Bean(name="security")public DefaultWebSecurityManager getDefaultManager(@Qualifier("realm")UserRealm userRealm){DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();//关联自己的realmdefaultSecurityManager.setRealm(userRealm);return defaultSecurityManager;}@Bean(name = "realm")//创建realm对象public UserRealm userRealm(){return new UserRealm();}

关联自定义的其他管理器

    @Beanpublic SecurityManager securityManager(UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 设置realm.securityManager.setRealm(userRealm);// 记住我securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);// 注入缓存管理器;securityManager.setCacheManager(getEhCacheManager());// session管理器securityManager.setSessionManager(sessionManager());return securityManager;}/*** 缓存管理器 使用Ehcache实现*/@Beanpublic EhCacheManager getEhCacheManager(){net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");EhCacheManager em = new EhCacheManager();if (StringUtils.isNull(cacheManager)){em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));return em;}else{em.setCacheManager(cacheManager);return em;}}

缓存:Shiro内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如Realm)是否实现了CacheManagerAware并自动注入相应的CacheManager。
Shiro提供了CachingRealm,其实现了CacheManagerAware接口,提供了缓存的一些基础实现;
•AuthenticatingRealm及AuthorizingRealm也分别提供了对AuthenticationInfo和AuthorizationInfo信息的缓存。
Session 缓存
•如SecurityManager实现了SessionSecurityManager,其会判断SessionManager是否实现了CacheManagerAware接口,如果实现了会把CacheManager设置给它。
•SessionManager也会判断相应的SessionDAO(如继承自CachingSessionDAO)是否实现了CacheManagerAware,如果实现了会把CacheManager设置给它
•设置了缓存的SessionManager,查询时会先查缓存,如果找不到才查数据库。

自定义会话工厂:

//自定义sessionFactory会话
@Component
public class OnlineSessionFactory implements SessionFactory
{@Overridepublic Session createSession(SessionContext initData){OnlineSession session = new OnlineSession();if (initData != null && initData instanceof WebSessionContext){WebSessionContext sessionContext = (WebSessionContext) initData;HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();if (request != null){UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));// 获取客户端操作系统String os = userAgent.getOperatingSystem().getName();// 获取客户端浏览器String browser = userAgent.getBrowser().getName();session.setHost(IpUtils.getIpAddr(request));session.setBrowser(browser);session.setOs(os);}}return session;}
}

3.登陆时记录用户信息

在控制器层:

   @ApiOperation(value="登录")
@PostMapping("/login")public ResponseResult<User> toLogin(@ApiParam(name="用户对象",value="传入json格式",required=true)LoginForm loginForm)
{User user = userService.selectUserByLoginName(loginForm.getUserName(),loginForm.getPassword(), false);if (user != null) {UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword(), false);Subject subject = SecurityUtils.getSubject();
subject.login(token);
return ResponseResult.success();}else return ResponseResult.error();
}

4.shiro一些工具类的学习

SecurityUtils.getSubject()是每个请求创建一个Subject, 并保存到ThreadContext的resources(ThreadLocal<Map<Object, Object>>)变量中,也就是一个http请求一个subject,并绑定到当前线程。
subject.login()登陆认证成功后,下一次请求如何知道是那个用户的请求呢?
内部原理:1个请求1个Subject原理:由于ShiroFilterFactoryBean本质是个AbstractShiroFilter过滤器,所以每次请求都会执行doFilterInternal里面的createSubject方法。
源码:


public interface Subject {Object getPrincipal();PrincipalCollection getPrincipals();boolean isPermitted(String var1);boolean isPermitted(Permission var1);...省略其他方法}public interface SecurityManager extends Authenticator, Authorizer, SessionManager {Subject login(Subject var1, AuthenticationToken var2) throws AuthenticationException;void logout(Subject var1);Subject createSubject(SubjectContext var1);
}public abstract class SecurityUtils {private static volatile SecurityManager securityManager;public SecurityUtils() {}public static Subject getSubject() {Subject subject = ThreadContext.getSubject();if (subject == null) {subject = (new Builder()).buildSubject();ThreadContext.bind(subject);}return subject;}public static void setSecurityManager(SecurityManager securityManager) {SecurityUtils.securityManager = securityManager;}public static SecurityManager getSecurityManager() throws UnavailableSecurityManagerException {SecurityManager securityManager = ThreadContext.getSecurityManager();if (securityManager == null) {securityManager = SecurityUtils.securityManager;}if (securityManager == null) {String msg = "No SecurityManager accessible to the calling code, either bound to the " + ThreadContext.class.getName() + " or as a vm static singleton.  This is an invalid application configuration.";throw new UnavailableSecurityManagerException(msg);} else {return securityManager;}}
}

shiro内置的session
session.setAttribute(“username”,username)就是将username保存到session中,session的key值为username,其信息(value)为username,或者引用值。这样以后可以通过session.getAttribute(“username”)的方法来获取这个对象。通常,当用户已经登录系统后,就可以在session中存储一个用户信息对象,伺候可以随时从session中将这个对象取出来进行一些操作,比如身份验证等等。

request.getSession()可以获得HttpSession类型的对象,通常称之为session对象,session对象的作用域为一次会话,通常浏览器不关闭,保存的值就不会消失,当然也会出现session超时。服务器里面可以设置session的超时时间,web.xml中有一个session time out的地方,tomcat默认为30分钟。
session. setAttribute(“key”,value)是session设置值的方法,原理同Map集合。
getAttribute的返回值类型是Object,需要向下转型,转成你的userName类型的。比如,String session1= (String)session.getAttribute(“student”) ;

5.自定义登录拦截器

这种办法不需要引入依赖,只需要继承HandlerInterceptor 即可 实现非常简单:

@Slf4j
public class UserLoginInterceptor implements HandlerInterceptor {/*** true 表示继续流程,false表示中断* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle...");User user = (User) request.getSession().getAttribute(MallConst.CURRENT_USER);if (user == null) {log.info("user=null");throw new UserLoginException();}return true;}
}

然后定义一个配置类,启动时springboot便能进行自动配置

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserLoginInterceptor()).addPathPatterns("/**")//自己添加需要拦截的路径.excludePathPatterns("/error", "/user/login", "/user/register", "/categories",  "/products/*");//哪些路径不需要拦截}
}

springboot整合shiro和session的详细过程和自定义登录拦截器相关推荐

  1. springboot整合shiro(超详细,你想要的都在这了)

    Springboot整合Shiro 文章目录 pom依赖 前端页面(thymeleaf整合shiro) thymeleaf中shiro标签解释 数据库(整合mybatis) 理解shiro的几个组成部 ...

  2. SpringBoot整合Shiro搭建登录注册认证授权权限项目模板

    主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...

  3. 补习系列(6)- springboot 整合 shiro 一指禅

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  4. SpringBoot 整合Shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  5. SpringBoot整合Shiro学习(上)

    SpringBoot整合Shiro(上) 基于[编程不良人]2020最新版Shiro教程,整合SpringBoot项目实战教程 哔哩哔哩链接:https://www.bilibili.com/vide ...

  6. SpringBoot整合Shiro实现权限管理与登陆注册

    前言 Shiro解决了什么问题? 互联网无非就是一些用户C想要使用一些服务S的资源去完成某件事,S的资源不能说给谁用就给谁用,因此产生了权限的概念,即C必须有权限才能操作S的资源.S如何确定C就是C呢 ...

  7. 降龙十八掌之 springboot整合shiro(含MD5加密)

    java学习爱好者 2019-05-27 16:21:00 开发环境: 1.mysql - 5.7.21 2.navicat(mysql客户端管理工具) 3.idea 2017 4.jdk9 5.to ...

  8. 补习系列- springboot 整合 shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  9. 补习系列(6)-SpringBoot 整合Shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

最新文章

  1. 深入探讨Java中的异常与错误处理
  2. STM32-通用定时器基本定时功能
  3. linux用c++调用动态库
  4. phalcon: 缓存片段,文件缓存,memcache缓存
  5. ASP.NET伪静态-无法读取配置文件,因为它超过了最大文件大小的解决办法
  6. 华为荣耀6 H60-L02/L12(联通版)救砖包【适用于无限重启】
  7. Linux fork的写时复制
  8. HttpResponse 类
  9. 字节跳动 MySQL 学习笔记火了,完整版开放下载!
  10. sql注入mysql判断_sql注入笔记二——数据库信息判断
  11. 《天天数学》连载37:二月六日
  12. webSphere报错:Error 500: javax.servlet.ServletException: SRVE0207E: Uncaught initialization
  13. [4.2]-AutoSAR零基础学习-XCP 测量/校准 <<2>>
  14. 深度学习与人脸识别系列(3)__利用caffe训练深度学习模型
  15. 在网上开店有哪些好处?最多可以开几个?
  16. echarts直角坐标系
  17. [论文总结] 育种理论与基因检测
  18. 从大数据挖掘大智慧,华为创造AI时代速度新高度
  19. c# 禁用鼠标与键盘
  20. 小白学习Python的第十六天之正则表达式

热门文章

  1. zookeeper版本更新_ZooKeeper入门,看这篇就够了!
  2. mysql 字符串不限长度,mysql中的字符串长度是否有限制?
  3. numpy 若干行和列_Numpy的轴,pandas的行和列
  4. 【数据结构与算法-2】链表
  5. android 许可协议,Android 基本控件的使用二(注册许可协议)(CheckBox)
  6. java window linux_java环境变量配置(Windows Linux)
  7. html密码框不显示,密码框中密码的显示与隐藏切换(JS)
  8. 命令行调用springboot服务_Spring Boot命令行界面的使用
  9. vo生成MySQL表_跟我学微服务统一开发平台-代码生成器
  10. 【小白学习C++ 教程】十二、C++面向对象编程中的构造函数和析构函数