在springboot中使用SHiro作为安全框架,非常简单,灵活性也比较高
在springboot中使用Shiro不用像官网教程那样,官网是将配置文件写在INI文件和XML配置中
springboot中提倡使用javaconfig的形式,所以这里都采用javaconfig的形式。
记录Shiro的初步使用(配置登录接口,认证成功的处理、认证失败的处理、无认证信息的处理)
进阶使用(使用缓存管理Shiro的Session和Cache)
完整版使用 (给出可在生产中使用的配置)
初步使用
- 自定义MyAuthorizingRealm类,继承类AuthorizingRealm,实现里面的doGetAuthorizationInfo和doGetAuthenticationInfo方法
AuthorizingRealm是Shiro提供的处理认证授权的抽象类,oGetAuthenticationInfo就是认证的处理,doGetAuthorizationInfo就是授权的处理。功能非常丰富。
- 自定义一个ShiroConfig类,对Shiro进行配置,主要是配置ShiroFilterFactoryBean,SecurityManager,DefaultWebSessionManager,AuthorizationAttributeSourceAdvisor
ShiroFilterFactoryBean,主要是配置某个Url的权限情况
DefaultWebSessionManager:对session进行管理,如命名、有效期等此处的Session是经过Shiro封装的session,扩展了相关属性。
AuthorizationAttributeSourceAdvisor:配置基于aop形式的授权校验,可在接口上通过注解添加权限处理
- 编写登录接口
使用Shiro提供的Subject对象,调用其login方法,即可完成登录。
登录时会调用之前在MyAuthorizingRealm类定义的doGetAuthenticationInfo的认证逻辑(获取身份信息、密码加盐加密等),这其中还会涉及一些缓存的操作,暂时按下不表。
如何自定义Shiro的Filter?
Shiro已经提供了很多实现好的过滤器,可参考org.apache.shiro.web.filter.mgt.DefaultFilter枚举类,里面有实现类和简写的映射关系。
常用的如 anon(AnonymousFilter.class),authc(FormAuthenticationFilter.class),logout(LogoutFilter.class)等。
实现:
- 自定义类CustomFormAuthenticationFilter extends FormAuthenticationFilter
- 注册CustomFormAuthenticationFilter到shiroFilterFactoryBean中
tips:CustomFormAuthenticationFilter在获取时,只能用构造器new出来,spring容器中无法自定注入该类
参考:
/**
* 在此配置拦截器栈
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("init ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//注册自定义filter 命名为authc 覆盖默认FormAuthenticationFilter
Map<String, Filter> filterMap = shiroFilterFactoryBean.getFilters();
filterMap.put("authc2", new CustomFormAuthenticationFilter());
shiroFilterFactoryBean.setFilters(filterMap);
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置不会被拦截的链接 顺序判断 注意过滤器配置顺序 不能颠倒
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
filterChainDefinitionMap.put("/logout.do", "logout");
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
// ajax方式的登录
filterChainDefinitionMap.put("/ajaxLogin.do", "anon");
// ajax方式的退出登录
filterChainDefinitionMap.put("/ajaxLogout.do", "anon");
filterChainDefinitionMap.put("/unauth.do", "anon");
filterChainDefinitionMap.put("/formLogin.do", "authc2");
filterChainDefinitionMap.put("/**", "authc");
// 表单登录地址 是指跳转到登录页的url 而不是指定登录接口
shiroFilterFactoryBean.setLoginUrl("/formLogin.do");
// 表单登录成功后的跳转地址
shiroFilterFactoryBean.setSuccessUrl("/loginSuccess.do");
// 请求未认证的跳转地址
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth.do");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
如何进行传统表单登录而不是ajax形式?
在config类中配置一个接口,并用authc(FormAuthenticationFilter.class)过滤器进行认证,即可走表单登录。
地雷
- ShiroFilterFactoryBean配置的地址坑很多
shiroFilterFactoryBean.setLoginUrl("/formLogin.do");
// 表单登录成功后的跳转地址
shiroFilterFactoryBean.setSuccessUrl("/loginSuccess.do");
// 请求未认证的跳转地址
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth.do");
LoginUrl配置的地址,是表单登录接口,但如果已经登录成功,再访问该接口重新登录,shiro并不会拦截到该接口,而是直接放行。springMVC会直接去寻找/formLogin.do接口,如果没有自定义该接口,就会报404
SuccessUrl是authc(FormAuthenticationFilter.class)处理登录成功后的跳转地址
UnauthorizedUrl是请求认证时发现无认证信息时,跳转的接口
- 配置可参考org.apache.shiro.spring.web.config包下的AbstractShiroWebConfiguration类,有一些参数配置文件的读取