前言
Apache Shiro 是 Java 的一个安全框架。功能强大,使用简单的Java安全框架,它为开发人员提供一个直观而全面的认证,授权,加密及会话管理的解决方案。
功能介绍
资源-角色-权限
登录认证,密码加密(Authentication, Authorization, Cryptography)
用户角色和权限放入缓存(Caching)
会话管理(Session Management)
功能实现
实现说明
基于Spring开发Shiro的话,我们只需要实现ShiroFilterFactoryBean即可。
ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
filterFactoryBean.setLoginUrl("/login");// 未登录时候跳转URL
filterFactoryBean.setSuccessUrl("/index");// 成功后欢迎页面
filterFactoryBean.setUnauthorizedUrl("/unAuthorized");// 未认证页面
filterFactoryBean.setSecurityManager(securityManager);
filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
上面我们看到:
SecurityManager是登录认证,缓存管理和会话管理等的具体实现;filterChainDefinitionMap是资源对应的各种Filter的实现;
资源-角色-权限
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// /user/下面的需要ROLE_USER角色
filterChainDefinitionMap.put("/user/**", "roles[ROLE_USER]");
// /admin/下面的所有需要ROLE_ADMIN的角色才能访问
filterChainDefinitionMap.put("/admin/**", "roles[ROLE_ADMIN]");
//登录注册不需要认证
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/register", "anon");
// 其他资源地址全部需要用户认证才能访问
filterChainDefinitionMap.put("/**", "authc");
上面是设置当用户请求某个api的时候,使用对应的filter进行拦截处理,从而判断是否有对应的权限;默认的filter有以下几种:
/**
* Enum representing all of the default Shiro Filter instances available to web applications. Each filter instance is
* typically accessible in configuration the {
@link #name() name} of the enum constant.
*
* @since 1.0
*/
public enum DefaultFilter {
anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class),
authcBasic(BasicHttpAuthenticationFilter.class),
logout(LogoutFilter.class),
noSessionCreation(NoSessionCreationFilter.class),
perms(PermissionsAuthorizationFilter.class),
port(PortFilter.class),
rest(HttpMethodPermissionFilter.class),
roles(RolesAuthorizationFilter.class),
ssl(SslFilter.class),
user(UserFilter.class);
登录认证,密码加密
因为用户信息和对应的角色权限信息,都是由应用方提供,所以Shiro抽象了一个接口,由应用方去实现这个接口(AuthorizingRealm),有两个方法需要应用方自己去实现:
//用户登录认证
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
//用户权限认证
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
以下是自己抽象了一个类:
@Slf4j
public abstract class AbstractAuthorizingRealm extends AuthorizingRealm {
public AbstractAuthorizingRealm() {
HashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(EhCacheManagerFactory.getCacheManager());
credentialsMatcher.setHashAlgorithmName(ShiroConstant.hashAlgorithmName);
credentialsMatcher.setHashIterations(ShiroConstant.hashIterations);//加密次数
credentialsMatcher.setStoredCredentialsHexEncoded(true);
setCredentialsMatcher(credentialsMatcher);
}
/**
* 获取当前用户的角色和权限
*/
public abstract RoleAndPermissions getRoleAndPermissionsFromUsername(String username);
/**
* 获取认证信息
* @param username 用户名
*/
public abstract UserAuthInfo getAuthInfoFromUsername(String username);
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.info("##################执行Shiro权限认证(默认)##################"