shrio
shrio是做权限管理的,对比于spring security是很轻量级的,但是对于功能也会相对有限制。
shrio的功能
功能就是认证(登录实现)、资源权限管理、记住我、加密等
基本简介
首先shrio的内部架构就是三个部分,subject就是指当前的用户(不一定的人)是shrio和外部的jpa、securityManager是对subject进行管理的,相当于一个过滤器和控制器,然后realm是可以自定义的,就是需要的相关的数据,可以看成是一个datasource.之后会从多个角度描述,会更加清晰。
认证实现以及原理
认证的过程就是前端发来用户名和密码(可能包含其他信息),形成一个subject之后交由securityManager进行相关的认证,认证的数据来源由Realm交付。
框架图,如下:
实现
1、首先需要对shrio进行配置
主要就是配置一些页面过滤条件,以及配置生成一个securityManager,并且将realm()将其配置进入securityManager中。(所以不管是什么功能,都需要注入到securityManager中)
@Configuration
public class ShiroConfig {
/**
* 设置过滤条件:auth:仅仅认证;user:允许曾经认证过的(记住我);anon;任何都可以
* perms:在一定权限下
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//以下是过滤链,按顺序过滤,所以/**需要放最后
//开放的静态资源
filterChainDefinitionMap.put("/userInfo/ajaxLogin","anon");
filterChainDefinitionMap.put("/images/**","anon");
filterChainDefinitionMap.put("/css/**","anon");
filterChainDefinitionMap.put("/js/**","anon");
filterChainDefinitionMap.put("/static/**","anon");
filterChainDefinitionMap.put("static/**","anon");
shiroFilterFactoryBean.setLoginUrl("/toLogin");
shiroFilterFactoryBean.setSuccessUrl("/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
// filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 安全管理器,Realm 添加进来
* @return
*/
//SecurityManager 是 Shiro 架构的核心,通过它来链接Realm和Subject
@Bean(name="securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm());
defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
return defaultWebSecurityManager;
}
/**
* 自定义Realm
* @return
*/
@Bean
public Realm myRealm() {
Realm myRealm = new Realm();
return myRealm;
}
}
2、Realm配置
realm需要提供一些数据支持进行认证以及授权,负责拿到数据并且封装好交给shrio。(当然了,这里需要准备一些数据支持:mybatis和jpa都是可以的,实体类就可以是用户即可,然后有用户名和 密码,然后存在相应的sevice层实现简单的接口)
public class Realm extends AuthorizingRealm {
@Resource
private UserService userService;
@Resource
private RoleService roleService;
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取当前用户名
String username= (String) authenticationToken.getPrincipal();
//通过username从数据库中查找 User对象,如果找到,没找到.
//实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自