SpringBoot整合Shiro配置详解

一.shiro基本介绍

1、Shiro是Apache下的一个开源项目,我们称之为Apache Shiro。它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与spring Security 一样都是做一个权限的安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用的授权方式。shiro属于轻量级框架,相对于security简单的多,也没有security那么复杂。所以我这里也是简单介绍一下shiro的使用。

2、非常简单;其基本功能点如下图所示:

Authentication身份认证/登录,验证用户是不是拥有相应的身份;

Authorization授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

Session Manager会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web SupportWeb支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrencyshiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing提供测试支持;

Run As允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

High-Level Overview 高级概述

在概念层,Shiro 架构包含三个主要的理念:Subject,SecurityManager和 Realm。下面的图展示了这些组件如何相互作用,我们将在下面依次对其进行描述。

  • Subject:当前用户,Subject 可以是一个人,但也可以是第三方服务、守护进程帐户、时钟守护任务或者其它–当前和软件交互的任何事件。
  • SecurityManager:管理所有Subject,SecurityManager 是 Shiro 架构的核心,配合内部安全组件共同组成安全伞。
  • Realms:用于进行权限信息的验证,我们自己实现。Realm 本质上是一个特定的安全 DAO:它封装与数据源连接的细节,得到Shiro 所需的相关的数据。在配置 Shiro 的时候,你必须指定至少一个Realm 来实现认证(authentication)和/或授权(authorization)。

我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。

记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。

二.配置信息

1.添加maven依赖

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

2.Shiro配置类

@Configuration
public class ShiroConfigBean {

    //配置自定义的权限登录器
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }
    //session管理器
    @Bean("sessionManager")
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

    //配置核心安全事务管理器
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    
    /**
     * 注册DelegatingFilterProxy(Shiro)
     * 集成Shiro有2种方法:
     * 1. 按这个方法自己组装一个FilterRegistrationBean(这种方法更为灵活,可以自己定义UrlPattern,
     * 在项目使用中你可能会因为一些很但疼的问题最后采用它, 想使用它你可能需要看官网或者已经很了解Shiro的处理原理了)
     * 2. 直接使用ShiroFilterFactoryBean(这种方法比较简单,其内部对ShiroFilter做了组装工作,无法自己定义UrlPattern,
     * 默认拦截 /*)
     *
     */
//  @Bean
//  public FilterRegistrationBean filterRegistrationBean() {
//      FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
//      filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
//      //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理  
//      filterRegistration.addInitParameter("targetFilterLifecycle", "true");
//      filterRegistration.setEnabled(true);
//      filterRegistration.addUrlPatterns("/*");// 可以自己灵活的定义很多,避免一些根本不需要被Shiro处理的请求被包含进来
//      return filterRegistration;
//  }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
 
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 拦截器,必须用LinkedHashMap添加拦截规则
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // 设置login URL
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/LoginSuccess.action");
        // 未授权的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized.action");
        // src="jquery/jquery-3.2.1.min.js" 生效
        filterChainDefinitionMap.put("/jquery/*", "anon");
        // 设置登录的URL为匿名访问,因为一开始没有用户验证
        filterChainDefinitionMap.put("/login.action", "anon");
        
        filterChainDefinitionMap.put("/Exception.class", "anon");
        // 我写的url一般都是xxx.action,根据你的情况自己修改
        filterChainDefinitionMap.put("/*.action", "authc");
        // 退出系统的过滤器
        filterChainDefinitionMap.put("/logout", "logout");
        // 现在资源的角色
        filterChainDefinitionMap.put("/admin.html", "roles[admin]");
        // filterChainDefinitionMap.put("/user.html", "roles[user]");
        // 最后一班都,固定格式
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
 
    /*
     * 开启shiro aop注解支持 使用代理方式;所以需要开启代码支持;
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new 
        AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
 
    /**
     * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }
 
}

Shiro 的默认Filter工厂 对应的类

 Filter名称 类路径(点击可以进入官方介绍,强烈建议看看 )
 anon org.apache.shiro.web.filter.authc.AnonymousFilter
 authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
 authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
 logout org.apache.shiro.web.filter.authc.LogoutFilter
 noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
 perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
 port org.apache.shiro.web.filter.authz.PortFilter
 rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
 roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
 ssl org.apache.shiro.web.filter.authz.SslFilter
 user org.apache.shiro.web.filter.authc.UserFilter

 3.自定义Realm类

public class MyShiroRealm extends AuthorizingRealm {
 
	/**
	 * 认证(验证当前用户信息)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
 
		// 将AuthenticationToken强转为AuthenticationToken对象
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
 
		// 获得从表单传过来的用户名
		String username = upToken.getUsername();
 
		// 从数据库查看是否存在用户
		UserService userService = new UserService();
 
		// 如果用户不存在,抛此异常
		if (!userService.selectUsername(username)) {
			throw new UnknownAccountException("无此用户名!");
		}
 
		// 认证的实体信息,可以是username,也可以是用户的实体类对象,这里用的用户名
		Object principal = username;
		// 从数据库中查询的密码
		Object credentials = userService.selectPassword(username);
		// 颜值加密的颜,可以用用户名
		ByteSource credentialsSalt = ByteSource.Util.bytes(username);
		// 当前realm对象的名称,调用分类的getName()
		String realmName = this.getName();
 
		// 创建SimpleAuthenticationInfo对象,并且把username和password等信息封装到里面
		// 用户密码的比对是Shiro帮我们完成的
		SimpleAuthenticationInfo info = null;
		info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
 
		return info;
	}
 
	// 授权(验证权限时调用)
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
 
		// User user=(User)
		// principals.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户
		// System.out.println("在MyShiroRealm中AuthorizationInfo(授权)方法中从session中获取的user对象:"+user);
 
		// 从PrincipalCollection中获得用户信息
		Object principal = principals.getPrimaryPrincipal();
		System.out.println("ShiroRealm  AuthorizationInfo:" + principal.toString());
 
		// 根据用户名来查询数据库赋予用户角色,权限(查数据库)
		Set<String> roles = new HashSet<>();
		Set<String> permissions = new HashSet<>();
		roles.add("user");
		permissions.add("user:query");
		if ("admin".equals(principal)) {
			roles.add("admin");
			permissions.add("admin:query");
		}
 
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
		//天加权限
		info.setStringPermissions(permissions);
		return info;
		// return null;
	}
 
}
  • doGetAuthenticationInfo执行时机如下

(1).当调用Subject currentUser = SecurityUtils.getSubject();

currentUser.login(token);

  • doGetAuthorizationInfo执行时机有三个,如下:

​​​​​​​(1).subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;

​​​​​​​(2).@RequiresRoles("admin") :在方法上加注解的时候;

​​​​​​​(3).[@shiro.hasPermission name = "admin"][/@shiro.hasPermission]:在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。

转载于:https://my.oschina.net/warm6Y/blog/2994224

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程简介:历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值