1.导入基于Shiro的数据库脚本
例如:
t_sys_user
t_sys_role
t_sys_permission
t_sys_user_role
t_sys_role_permission
关联关系:
用户与角色 角色与权限
用户--------------角色---------------权限
2.自定义Realm
Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
最基础的是Realm接口,CachingRealm负责缓存处理,AuthenticationRealm负责认证,AuthorizingRealm负责授权。
通常自定义的realm继承AuthorizingRealm
注1:体系结构见“shiro提供的realm.png”
AuthorizationInfo:授权信息
AuthenticationInfo:认证信息
3.Spring与Shiro集成
-
配置自定义Realm
//注入UserService实现类,通过账号密码登录时实现基于Shiro身份认证识别//盐加密算法配置,详见7.2
-
注册安全管理器
将自定义的Realm设置到Shiro的SecurityManager中,在Shiro授权和认证时使用自定义的Realm数据源进行校验
- 配置Shiro核心过滤器
Shiro核心过滤器用于拦截请求,通过给定的授权认证机制对用户访问身份和权限进行认证识别
详见“Shiro核心过滤器配置.txt”
filterChainDefinitions Shiro过滤链定义类型:
(1) anon,authcBasic,auchc,user是认证过滤器
(2) perms,roles,ssl,rest,port是授权过滤器
- 配置Shiro生命周期
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
4.修改web.xml文件,添加shiroFilter的配置
注:使用的代理类DelegatingFilterProxy
如:
<!-- shiro过滤器定义 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5.创建LoginController实现Shiro身份认证登录
//用户登录
public String login(请求参数){
…
//关键代码
Subject subject=SecurityUtils.getSubject();
UsernamepasswordToken token=new UsernamepasswordToken(
账号,
密码
);
subject.login(token);
…
}
//退出登录
public String logout(){
…
//关键代码
Subject subject=SecurityUtils.getSubject();
subject.logout();
…
}
6.创建login.jsp
7.盐加密
md5
7.1 生成加密密码PasswordHelper类(盐加密)
MD5+散列1024+Hex/Base64
如:
package com.zking.ssm.util;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
/**
* 用于shiro权限认证的密码工具类
*/
public class PasswordHelper {
/**
* 随机数生成器
*/
private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
/**
* 指定hash算法为MD5
*/
private static final String hashAlgorithmName = "md5";
/**
* 指定散列次数为1024次,即加密1024次
*/
private static final int hashIterations = 1024;
/**
* true指定Hash散列值使用Hex(十六进制)加密存. false表明hash散列值用用Base64-encoded存储
* 嵌入式编程
*/
private static final boolean storedCredentialsHexEncoded = true;
/**
* 获得加密用的盐
*
* @return
*/
public static String createSalt() {
return randomNumberGenerator.nextBytes().toHex();
}
/**
* 获得加密后的凭证
*
* @param credentials 凭证(即密码)
* @param salt 盐
* @return
*/
public static String createCredentials(String credentials, String salt) {
SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,
salt, hashIterations);
return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();
}
/**
* 进行密码验证
*
* @param credentials 未加密的密码
* @param salt 盐
* @param encryptCredentials 加密后的密码
* @return
*/
public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {
return encryptCredentials.equals(createCredentials(credentials, salt));
}
public static void main(String[] args) {
//盐
String salt = createSalt();
System.out.println("随机生成的盐:"+salt);
System.out.println(salt.length());
//凭证+盐加密后得到的密码
String credentials = createCredentials("123", salt);
System.out.println("加密后的串:"+credentials);
System.out.println(credentials.length());
boolean b = checkCredentials("123", salt, credentials);
System.out.println(b);
}
}
7.2 修改applicationContext-shirod的自定义Realm配置,增加以下:
<!-配置Shiro明文密码如何进行加密->
ByteSource.Util.bytes(user.getSalt())