- 概念: Apache Shiro 是一个强大且易用的 Java 安全框架
- 能做什么:Shiro可以帮我们完成 :认证、授权、加密、会话管理、与 Web 集成、缓存等。

主要认识:
- Subject(用户):
当前的操作用户 获取当前用户Subject currentUser = SecurityUtils.getSubject()
- SecurityManager(安全管理器):
Shiro的核心,负责与其他组件进行交互,实现 subject 委托的各种功能
- Realms(数据源) :
Realm会查找相关数据源,充当与安全管理间的桥梁,经过Realm找到数据源进行认 证,授权等操作
- Authenticator(认证器):
用于认证,从 Realm 数据源取得数据之后进行执行认证流程处理。
- Authorizer(授权器):
用户访问控制授权,决定用户是否拥有执行指定操作的权限。
- SessionManager (会话管理器): 支持会话管理
- CacheManager (缓存管理器): 用于缓存认证授权信息
- Cryptography(加密组件): 提供了加密解密的工具包
认证的关键对象:
Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体Principal:身份信息
身份信息,是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)credential:凭证信息
凭证信息,是只有主体自己知道的安全信息,如密码、证书等认证流程


将用户(主体)的用户名(身份信息)和密码(凭证信息)封装成Token(令牌)对象给到安全管理器进行校验 ```xmlorg.apache.shiro shiro-core 1.5.3
<a name="vgEHU"></a>##### 常见的异常类型- DisabledAccountException(帐号被禁用)- LockedAccountException(帐号被锁定)- ExcessiveAttemptsException(登录失败次数过多)- ExpiredCredentialsException(凭证过期)等<a name="WsqgG"></a>### 认证代码```java//1.创建安全管理器对象DefaultSecurityManager securityManager = new DefaultSecurityManager();//2.给安全管理器设置realmsecurityManager.setRealm(new IniRealm("classpath:shiro.ini"));//3.SecurityUtils给全局安全工具类设置安全管理器SecurityUtils.setSecurityManager(securityManager);//4.关键对象subject主体Subject subject = SecurityUtils.getSubject();//5.创建令牌UsernamePasswordToken token = new UsernamePasswordToken("zax","123456");try {System.out.println("认证状态"+subject.isAuthenticated());//fasle//用户认证subject.login(token);System.out.println("认证状态"+subject.isAuthenticated());}catch (UnknownAccountException e){e.printStackTrace();System.out.println("认证失败,用户名不存在");}catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("认证失败,密码错误");}

SimpleAccountRealm的部分源码中有两个方法一个是 认证 一个是 授权
MD5+salt+hash散列
//使用md5Md5Hash md5Hash = new Md5Hash("123");System.out.println(md5Hash.toHex());//使用MD5 + salt处理Md5Hash md5Hash1 = new Md5Hash("123", "X0*7ps");System.out.println(md5Hash1.toHex());//使用md5 + salt + hash散列(参数代表要散列多少次,一般是 1024或2048)Md5Hash md5Hash2 = new Md5Hash("123", "X0*7ps", 1024);System.out.println(md5Hash2.toHex());
自定义Realm类
package com.kgc.dmeo.test;import com.kgc.dmeo.entity.User;import com.kgc.dmeo.service.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.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;/*** 自定义Realm*/@Componentpublic class CustomerRealm extends AuthorizingRealm {@Autowired(required = false)private UserService userService;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//获取 token中的 用户名String principal = (String) token.getPrincipal();//假设这是从数据库查询到的信息// String username="zhangsan";// String password="7268f6d32ec8d6f4c305ae92395b00e8";//加密后User user = userService.getUserById(principal);//根据用户名查询数据库// username.equals(principal)if (user!=null) {//参数1:数据库用户名//参数2:数据库md5+salt之后的密码//参数3:注册时的随机盐//参数4:realm的名字return new SimpleAuthenticationInfo(principal,user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());}return null;}}
//1.创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();//2.注入realmCustomerRealm realm = SpringUtil.getBean(CustomerRealm.class);//3.设置realm使用hash凭证匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();//声明:使用的算法credentialsMatcher.setHashAlgorithmName("md5");//声明:散列次数credentialsMatcher.setHashIterations(1024);//设置凭证匹配器realm.setCredentialsMatcher(credentialsMatcher);//将realm放入安全管理器中defaultSecurityManager.setRealm(realm);//4.将安全管理器注入安全工具SecurityUtils.setSecurityManager(defaultSecurityManager);//5.通过安全工具类获取subjectSubject subject = SecurityUtils.getSubject();//6.认证UsernamePasswordToken token = new UsernamePasswordToken("12121", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("密码错误");}
授权
授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。 
授权方式

shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限:
