1. 可以看到web.xml中配置了过滤器过滤了所有的请求,Shiro把这些请求分为不拦截的请求和拦截的请求。
- 不拦截的请求可以是经过认证的请求,也可以是在spring中配置的过滤器类中的filterChainDefinitions属性规定的可以匿名访问的或者没有在该属性中规定的请求。
- 该属性规定的需要认证的请求会被拦截,然后重定向到配置好的登录页面。
- 注意:web.xml配置的过滤器是spring包里的,它会在spring容器中找和此过滤器名称对应的bean,所以bean的id要和过滤器名称一致。(当然,如果非要用不一样的名字,也可以配置一个targetBeanName属性)。
- 配置过滤请求的时候
- 问好匹配单个字符、一个星号匹配0个和多个字符串、两个星号匹配多重路径
- 前面的配置会覆盖后面的配置
2. 登录认证(将表单页面提交到实现认证的Controller中(注意在Shiro的过滤器bean中放行这个Controller))
1). 获取当前的Subject。调用SecurityUtils.getSubject();
2). 测试当前的用户是否已经被认证。调用Subject的IsAuthenticated();方法
3). 若没有被认证,则把从表单得到的用户名和密码封装为UsernamePasswordToken对象
4). 执行登录,调用Subject的Login(AuthenticationToken)方法。
5). 自定义Realm类(这个Realm类是要作为一个Bean配置在Spring中的),从数据库中获取对应的记录,返回给Shiro,继承org.apache.shiro.realm.AuthenticatingRealm类(这应该是个抽象类),实现doGetAuthenticationInfo(AuthenticationToken);方法
实现该Realm方法的步骤:
- 将AuthenticationToken强转为UsernamePasswordToken
- 从UsernamePasswordToken中获取到username。使用getUsername方法
- 查询数据库,得到用户名对应的信息
- 根据用户信息抛一些异常,例如UnknownAccountException异常,LockedAccountException异常
- 根据用户情况构建AuthenticationInfo(这应该也是个抽象类)对象返回,常用的实现类为:SimpleAuthenticationInfo,有三个参数principal:认证的实体信息,credentials:数据库中的密码,realmName:当前realm对象的name,调用父类的getName方法即可。
3. 密码加密
密码比对:通过AuthenticatingRealm的credentialsMatcher属性来进行密码比对。也就是自己实现的Realm继承的类的属性。
1. 如何把一个字符串加密为MD5?
使用Shiro带的类,SimpleHash,传入参数之后构造出该类,该类的toString方法即可得到加密后的字符串。
//TODO 注意这里的参数要和配置文件中Realm的属性设置的一样否则得不到正确密码
//加密类型
String algorithmName = "MD5";
//加密数据
Object source = "密码";
//盐
Object salt = ByteSource.Util.bytes("一个唯一的固定的随机字符串");
//加密次数
int hashIterations = 1810;
SimpleHash simpleHash = new SimpleHash(algorithmName, source, salt, hashIterations);
- 替换当前的Realm的credentialsMatcher属性为HashedCredentialsMatcher对象,并设置属性加密算法
- 还记得在spring的配置文件中配置了我们自定义的Realm类吗,在那个配置里设置它的属性值
- 设置credentialsMatcher属性为shiro里面提供的HashedCredentialsMatcher类。
- 然后给HashedCredentialsMatcher类的hashAlgorithmName(应该是加密类型)设置值为MD5,hashIterations(加密次数)为1810
<bean id="jdbcRealm" class="com.xxx.ShiroRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="1810"/>
</bean>
</property>
</bean>