Apache Shiro 是一个强大而灵活的开源安全框架,从官网上,我们基本上可以了解到,她提供的服务非常明确:
1.Authentication(认证)
2.Authorization(授权)
3.Session Management(会话管理)
4.Cryptography(加密)
org.apache.shiro
shiro-all
1.4.0
org.apache.shiro
shiro-cas
1.2.0
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
/checkpreload.htm = anon
/agent.ateye = anon
/agent.jveye = anon
/ = authc
/login/callback.htm = anon
/login/login.htm = anon
/login/checkLogin.htm = anon
/login/unauthorized.htm = anon
/login/changeSeller.htm = authc
/login/logout = logout
/login/api/** = anon
/login/** = anon
/** = authc
property name="filters"可以配置我们自定义的filter
shiron自带的filter如下我们可以继承这些filter来实现自己需要的一些功能,这些filter也就是filterChainDefinitions过滤规则所执行的filter我们可以根据过滤条件选择我们需要继承的filter
Filter Name | Class | 含义 |
---|---|---|
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | 没有参数,表示可以匿名使用。 |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | 表示需要认证(登录)才能使用,没有参数 |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | 没有参数表示httpBasic认证 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | |
noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter | |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms[“user:add:,user:modify:”],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。 |
port | org.apache.shiro.web.filter.authz.PortFilter | 当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。 |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter | 根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。 |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles[“admin,guest”],每个参数通过才算通过,相当于hasAllRoles()方法。 |
ssl | org.apache.shiro.web.filter.authz.SslFilter | 表示安全的url请求,协议为https |
user | org.apache.shiro.web.filter.authc.UserFilter | 没有参数表示必须存在用户,当登入操作时不做检查 |
cacheManager和sessionDAO的区别:
cacheManager缓存里可以包含权限认证的缓存、用户及权限信息的缓存等,也可以做session缓存。但是sessionDAO顾名思义就是做session持久化的,只是它刚好可以使用redis来存储而已。是完全不同的两个概念,通俗来说cacheManager是用来存储用户信息的sessionDAO是用来做session缓存的。
public class ShiroRedisCacheManager implements CacheManager, Initializable, Destroyable {
private String keyPrefix = "shiro_redis_cache:";
//ShiroRedisManager 为redis工具类
private ShiroRedisManager redisManager;
@Override
public Cache getCache(String name) throws CacheException {
//RedisCache为Cache 实现类 实现类方法内通过redisManager进行数据操作
Cache c = new RedisCache(redisManager, keyPrefix);
return c;
}
}
实现CacheManager接口就可以了
/** * Description:shiro框架 自定义session获取方式 *
可自定义session获取规则。这里采用ajax请求头authToken携带sessionId的方式 * **/ public
class ShiroSessionManager extends DefaultWebSessionManager {private static final String AUTHORIZATION = "authToken"; private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; public ShiroSessionManager(){ super(); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response){ String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION); System.out.println("id:"+id); if(StringUtils.isEmpty(id)){ //如果没有携带id参数则按照父类的方式在cookie进行获取 System.out.println("super:"+super.getSessionId(request, response)); return super.getSessionId(request, response); }else{ //如果请求头中有 authToken 则其值为sessionId request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID,id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID,Boolean.TRUE); return id; } }
public class OauthRealm extends AuthorizingRealm {
// 设置realm的名称
@Override
public void setName(String name) {
super.setName("customRealm");
}
@Autowired
private AdminUserService adminUserService;
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// token中包含用户输入的用户名和密码
// 第一步从token中取出用户名
String userName = (String) token.getPrincipal();
// 第二步:根据用户输入的userCode从数据库查询
TAdminUser adminUser = adminUserService.getAdminUserByUserName(userName);
// 如果查询不到返回null
if (adminUser == null) {//
return null;
}
// 获取数据库中的密码
String password = adminUser.getPassword();
/**
* 认证的用户,正确的密码
*/
return SimpleAuthenticationInfo(adminUser, token.getCredentials(), getName());
}
/**
* 授权,只有成功通过doGetAuthenticationInfo方法的认证后才会执行。
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 从 principals获取主身份信息
// 将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
TAdminUser activeUser = (TAdminUser)SecurityUtils.getSubject().getPrincipal();
// 根据身份信息获取权限信息
// 从数据库获取到角色数据
TAdminRole roles= adminUserService.getAdminRoles(activeUser);
//遍历角色下的功能位
for (RoleDO role : roles) {
Set permissionList = new HashSet<>();
List functionBits = role.getFunctionBitList();
for (int i = 0; i < functionBits.size(); i++) {
permissionList.add(functionBits.get(i) + "");
}
//将功能位列表就是最终的权限 通过在控制层@RequiresPermissions("3")注解限制权限为3才可以访问
info.addStringPermissions(permissionList);
}
return simpleAuthorizationInfo;