这是一篇还算条例清晰地简介Apache Shiro的文章

因为平时工作的关系,本篇文章主要按照登录认证和权限管理两部分来介绍shiro。
0.基础介绍
0.0 做什么
我们先看看百度百科怎么介绍“Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序”。由此可以看出来,Apache Shiro主要做三件事,登录认证、权限管理和会话管理。
0.1 组件介绍
Apache Shiro的架构图如下:

在这里插入图片描述

Subject:Subject 不仅仅代表某个用户,与当前应用交互的任何东西都是Subject,如网络爬虫等。所有的Subject都要绑定到SecurityManager上,与Subject的交互实际上是被转换为与SecurityManager的交互。
SecurityManager:即所有Subject的管理者,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。作用类似于SpringMVC中的DispatcherServlet,用于拦截所有请求并进行处理。

Realm:Realm是用户的信息认证器和用户的权限人证器,我们需要自己来实现Realm来自定义的管理我们自己系统内部的权限规则。SecurityManager要验证用户,需要从Realm中获取用户。可以把Realm看做是数据源。

Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得Shiro默认的不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;

Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;

SessionManager:管理主体与应用之间交互的数据;如果我们在Web环境用,刚开始是一台Web服务器;接着又上了台EJB服务器;这时想把两台服务器的会话数据放到一个地方,就可以实现自己的分布式会话。

SessionDAO:DAO大家都用过,数据访问对象,用户会话数据的CURD。

CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的。

Cryptography:密码模块。

1 登录认证
1.1介绍
实际上,按照我们平时的系统的系统,我们在登录认证的时候,只需要关注三个点。第一,在哪里输入(传入)账密?第二,在哪里认证这些传入的账密?第三,如果告诉系统或者容器,认证的结果?
1.2,认证流程
在这里插入图片描述
如上图所示,身份认证流程如下:
(1) 首先调用 subject.login(token) 进行登录认证,自动委托给 SecurityManager,调用前必须获取 SecurityManager 实例且要将此实例绑定给 SecurityUtils;
(2) SecurityManager 负责身份认证逻辑,会委托给 Authenticator 进行身份认证;
(3) Authenticator 才是真正的身份认证负责人,是 Shiro API 中核心的身份认证入口点,可以自定义插入自己的身份认证实现逻辑;
(4) Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份认证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份认证;
(5) Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份认证信息,如果抛出异常表示身份认证失败。可以配置多个 Realm,将按照对应的顺序及策略进行访问。
1.3,在哪里传入账密?
代码实现如下

       // 1.获取SecurityManager工厂,使用ini配置文件初始化SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        // 2.获取SecurityManager实例
        SecurityManager securityManager = factory.getInstance();
        // 3.将SecurityManager实例绑定给SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 4.通过SecurityUtils获取Subject
        Subject subject = SecurityUtils.getSubject();
        // 5.创建用户名、密码身份验证token
        UsernamePasswordToken token = new UsernamePasswordToken("zdtest", "aaaaa888");
        try {
            // 6.使用用户名、密码身份验证token进行身份验证,即登录
            subject.login(token);
        } catch (AuthenticationException e) {
           

1.4,realm实现
realm是实现校验账密的地方,主要和数据库打交道。
如下配置realm

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm1" />
	</bean>

realm的实现如下

public class CustomRealm1 implements Realm {

    @Override
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) 
        throws AuthenticationException {
        // 获取用户名
        String username = (String) token.getPrincipal();
        // 获取密码
        String password = new String((char[]) token.getCredentials());
        // 如果用户名错误
        if (!"zdtest".equals(username)) {
            throw new UnknownAccountException();
        }
        // 如果密码错误
        if (!"aaaaa888".equals(password)) {
            throw new IncorrectCredentialsException();
        }
        // 如果身份认证验证成功,返回一个AuthenticationInfo接口实现
        return new SimpleAuthenticationInfo(username, password, getName());
    }

    @Override
    public String getName() {
        return "CustomRealm1";
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

}

2,授权
在大家访问系统的时候,一般情况下会遇见如下三种情况:
1)访问的url资源不需要任何角色,既可以访问。
2)没有访问的资源需要角色,被拦截到登录页面。
3)有访问资源需要的角色,正常访问。
2.1,shiro角色控制的颗粒度
anon 未认证可以访问
authc 认证后可以访问
perms 需要特定权限才能访问
roles 需要特定角色才能访问
user 需要特定用户才能访问
port 需要特定端口才能访问
reset 根据指定 HTTP 请求访问才能访问
perms[courier:list]:用于用户权限控制
2.2,shiro的filter核心配置

    <!-- 配置Shiro核心Filter -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 安全管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 未认证,跳转到哪个页面 -->
		<property name="loginUrl" value="/login.html" />
		<!-- 登录页面页面 -->
		<property name="successUrl" value="/index.html" />
		<!-- 认证后,没有权限跳转页面 -->
		<property name="unauthorizedUrl" value="/unauthorized.html" />
		<!-- shiro URL控制过滤器规则 -->
		<property name="filterChainDefinitions">
			<value>
				/login.html* = anon
				/user_login.action* = anon
				/validatecode.jsp* = anon
				/css/** = anon
				/js/** = anon
				/images/** =anon
				/pages/base/courier.html* = perms[courier:list]
				/pages/base/area.html* = roles[base]
				/** =authc
			</value>
		</property>
	</bean>

2.3,shiro授权的实现。
首先自定义realm需要实现AuthorizingRealm 。实现其中的doGetAuthorizationInfo接口。

   @Override
	// 授权...
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
		System.out.println("shiro 授权管理...");
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		// 根据当前登录用户 查询对应角色和权限
		Subject subject = SecurityUtils.getSubject();
		User user = (User) subject.getPrincipal();
		// 调用业务层,查询角色
		List<Role> roles = roleService.findByUser(user);
		for (Role role : roles) {
			authorizationInfo.addRole(role.getKeyword());
		}
		// 调用业务层,查询权限
		List<Permission> permissions = permissionService.findByUser(user);
		for (Permission permission : permissions) {
			authorizationInfo.addStringPermission(permission.getKeyword());
		}
		return authorizationInfo;
	}

终上所述,shiro能够很好很方便的实现用户的登录与授权工作,用户只需要实现其中的关键接口就行了,使用起来还是非常方便,配置也是相当的灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值