最近很忙,没有时间详细记录,只能简单写下流程为了温故而知新吧,毕竟是宝贵的项目经验 ...
下面就是我写项目时的一些流程和注意点:
- 首先明确前后端分离是用json传数据
- 前后端分离逃不过跨域,但是后台只要配置filter就可
- 解决以上2点vue+ssm项目基本没问题了
- 加上shiro后就出现了很多问题:
- 首先明白authc,anon.user是shiro内置的filter,而这些filter往往不能满足我们的需求,所以我们需要重写,这就需要阅读源码的功底了,网上的配置也不可能刚好符合你需求
加上shiro后发请求出现options,导致真正的post请求无法发送,解决办法:访问权限为anon的不需要考虑,不会出现options请求(我也没弄懂),当权限为user,authc时就会出现options,我是重写filter来预先处理options,一但遇到这个请求立马放行,这样客户端就会收到options返回的true信息,会紧接着发送第二次请求(真正的请求)
//继承的实际就是authc代表的过滤器,可以查阅源码重写父类的方法实现需求
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{
//顾名思义,这是判断时候允许通过的方法,在这个方法里处理了options请求,
然后接下来直接调用父类的方法实现着个方法真正需要做的事-----总结起来就是我们重写filter时
,如果你能力够那么你彻底覆写也没问题,
相反,你可以先添加代码实现自己的需求,
再调用父类同名的方法实现这个方法在shiro真正做到的功能
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
//处理options请求
if (request instanceof HttpServletRequest) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
}
//如果不是option请求则调用父类方法处理
return super.isAccessAllowed(request, response, mappedValue);
}
//请求未通过,肯定是没有通过shiro的认证
//重写这个方法防止跳转到Login
//自己看源码
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
throws Exception {
//防止乱码,适用于传输JSON数据
((HttpServletResponse) response).setHeader("Content-Type","application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println(JSONObject.toJSON(new ErrorMessage(0,"您还没有通过认证")));
out.flush();
out.close();
//不跳转到Login
return false;
}
}
就这么多了,写的很乱,能看的懂得人应该看得懂,看不懂得就图个乐吧----累了,睡觉!
附上项目shiro配置:
<!--1. 配置securityManager安全管理器 -->
<!--
SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;
且它管理着所有Subject;可以看出它是Shiro 的核心,它负责与后边介绍的其他组件进行交互
-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroDbRealm" />
<!--记住我-->
<property name="rememberMeManager" ref="rememberMeManager"/>
<!-- 配置sessionManager,提供session管理 -->
<property name="sessionManager" ref="sessionManager"></property>
</bean>
<!--2. 配置 CacheManager. 2.1需要加入 ehcache 的 jar 包及配置文件. -->
<bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager">
</bean>
<!-- shiro结合Session会话管理器 start -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session的失效时长,单位毫秒 1小时: 3600000, itzixi站点设置以 6小时 为主:21600000 -->
<!-- 设置全局会话超时时间,默认30分钟,即如果30分钟内没有访问会话将过期 1800000 -->
<property name="globalSessionTimeout" value="21600000"/>
<!-- 删除失效的session -->
<property name="deleteInvalidSessions" value="true"/>
<!-- 是否开启会话验证器,默认是开启的 -->
<property name="sessionValidationSchedulerEnabled" value="true"/>
</bean>
<!--rememberMe cookie-->
<bean id="rememberMe" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"></constructor-arg>
<property name="httpOnly" value="true"></property>
<!--cookie 的最大失效时间 30天-->
<property name="maxAge" value="259200"></property>
</bean>
<!-- Remember me管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"></property>
<property name="cookie" ref="rememberMe"></property>
</bean>
<!--3.配置realm 自定义的Realm-->
<!--
Shiro 从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,
那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;
也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;
可以把Realm看成DataSource , 即安全数据源
-->
<bean id="shiroDbRealm" class="cn.xust.realm.accountRealm"></bean>
<!--4.配置lifecycleBeanPostProcessor,可以自动调用spring ioc 容器中的shiro bean 的生命周期方法 -->
<!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!--5. 启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor 之后才可以使用. -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<!-- Shiro Filter id值和web.xml文件配置的过滤器名称相同 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 登录页面 -->
<!-- 只要没验证通通定向到此页面 -->
<!-- Shiro过滤器链 -->
<property name="filters">
<util:map>
<entry key="authc" value-ref="CustomFormAuthenticationFilter" />
</util:map>
</property>
<!-- 登录成功页面 -->
<!-- <property name="successUrl" value="/success.jsp"/>-->
<!-- 没有权限的页面 -->
<!-- 注意:直接访问需要权限的页面(没有验证时)都会被定向到 loginUrl,而不会被unauthorizedUr拦截,只有内部跳转进入realm权限验证才会被此拦截-->
<!-- <property name="unauthorizedUrl" value="/NoAccess.jsp"/> -->
<!--
配置哪些页面需要受保护.
以及访问这些页面需要的权限.
1). anon 可以被匿名访问
2). authc 必须认证(即登录)后才可能访问的页面.
3). logout 登出.
4). roles 角色过滤器
-->
<property name="filterChainDefinitions">
<value>
/logout = logout
/user/login = anon
/user/register = anon
/user/email = anon
/** = authc
</value>
</property>
</bean>
<!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 定义扩展的filter实例 -->
<bean id="CustomFormAuthenticationFilter" class="cn.xust.filter.CustomFormAuthenticationFilter" />
<bean id="ShiroUserFilter" class="cn.xust.filter.ShiroUserFilter" />