源代码注释可见 https://github.com/chenbo19867758/jeecmsV8-BoBo.git

1.后台登录页面

/jeeadmin/jeecms/login.do
  • 1

web.xml中

<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!--
targetFilterLifecycle 允许代理注入Spring bean
解决因为filter比bean先加载,也就是spring会先加载filter指定的类到container中,这样filter中注入的spring
bean就为null了 设置为true由servlet容器控制filter的生命周期
-->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<!--
设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean 这里未设置 自动找到
shiro-context.xml 中的 shiroFilter bean 过滤 <init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value> </init-param>
-->
</filter>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

shiro-context.xml 配置了

/jeeadmin/jeecms/login.do = authc
  • 1

请求登录时会进入自定义过滤器 authcFilter

<bean id="authcFilter" class="com.jeecms.core.security.CmsAuthenticationFilter"
parent="adminUrlBean">
<!-- 登录成功后进入的页面 -->
<property name="adminIndex" value="/jeeadmin/jeecms/index.do" />
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5

CmsAuthenticationFilter 中

    public boolean onPreHandle(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
boolean isAllowed = isAccessAllowed(request, response, mappedValue);
// 判断是否登录页面的请求,转向登录页面
if (isAllowed && isLoginRequest(request, response)) {
try {
issueSuccessRedirect(request, response);
} catch (Exception e) {
logger.error("", e);
}
return false;
}
return isAllowed || onAccessDenied(request, response, mappedValue);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
    /**
* 在这返回成功页面successUrl
*/
protected void issueSuccessRedirect(ServletRequest request, ServletResponse response)
throws Exception {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String successUrl = req.getParameter(RETURN_URL);
if (StringUtils.isBlank(successUrl)) {
if (req.getRequestURI().startsWith(
req.getContextPath() + getAdminPrefix())) {
// 后台直接返回首页,这里为 /jeeadmin/jeecms/index.do
successUrl = getAdminIndex();
// 清除SavedRequest
WebUtils.getAndClearSavedRequest(request);
WebUtils.issueRedirect(request, response, successUrl, null,true);
return;
} else {
// 返回默认的成功页,AuthenticationFilter 中 DEFAULT_SUCCESS_URL = "/";
successUrl = getSuccessUrl();
}
}
WebUtils.getAndClearSavedRequest(request);
WebUtils.issueRedirect(request, response, successUrl, null,true);
//WebUtils.redirectToSavedRequest(req, res, successUrl);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

判断是否登录页面的请求, 登录页面转向的成功页面,并区分前端登录和后端登录

登录失败则跳转到spring mvc 映射的路径, CmsLoginAct 中

// 登录失败转向这里
// submit 名称不是固定的随便取, 只需匹配 @RequestMapping
@RequestMapping(value = "/login.do", method = RequestMethod.POST)
public String submit(String username, HttpServletRequest request,
HttpServletResponse response, ModelMap model) {
Object error = request.getAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
if (error != null) {
model.addAttribute("error", error);
Integer errorRemaining= unifiedUserMng.errorRemaining(username);
model.addAttribute("errorRemaining", errorRemaining);
}
//此方法不处理登陆成功(认证成功),shiro认证成功会自动跳转到上一个请求路径
//登陆失败还到login页面
return "login";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

shiro详解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"
default-lazy-init="true"> <!-- web.xml中 对应名称 <filter-name>shiroFilter</filter-name> -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- /login.jspx 前端用户登录地址 -->
<property name="loginUrl" value="/login.jspx" />
<!-- successUrl认证成功统一跳转地址,不配置,shiro认证成功自动到上一个请求路径 -->
<property name="successUrl" value="/" /> <!--
这是因为shiro源代码中判断了filter是否为AuthorizationFilter,
只有perms,roles,ssl,rest,port才是属于AuthorizationFilter(授权),
而anon,authcBasic,auchc,user是AuthenticationFilter(验证),所以unauthorizedUrl(未被授权的url)设置后不起作用。
这里不需要配置 unauthorizedUrl
--> <!-- 自定义filter配置 -->
<property name="filters">
<util:map>
<!-- 下面配置 authcFilter bean -->
<entry key="authc" value-ref="authcFilter" />
<!-- 下面配置 userFilter bean -->
<entry key="user" value-ref="userFilter" />
<!-- 退出过滤器, 下面配置 logoutFilter bean -->
<entry key="logout" value-ref="logoutFilter" />
</util:map>
</property>
<!--
anon匿名 authc登录认证 user用户已登录 logout退出filter anon:例子/admins/**=anon
没有参数,表示可以匿名使用。 authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数
roles(角色):例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
perms(权限):例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method]
,其中method为post,get,delete等。
port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。
authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查
user是介于,anon和authc直之间的。换句话来说:而“/authenticated=
user”表示访问该地址的用户是身份验证通过或RememberMe
登录的都可以。或者说,某个页面需要登录才能看,但这个页面信息又不太重要,就可已使用这个
-->
<!--
后台首页登录 /jeeadmin/jeecms/login.do 后台登录页面访问的接口
/jeeadmin/jeecms/login.do = authc 配置为需要验证权限登录 需要过来器<entry key="authc"
value-ref="authcFilter" /> 过滤
-->
<!--
filterChainDefinitions Shiro连接约束配置,即过滤链的定义
Shiro Filter的执行顺序 “ 自上而下,从左到右”
-->
<property name="filterChainDefinitions">
<value>
*.jspx = anon
*.jhtml = anon
/member/forgot_password.jspx = anon
/member/password_reset.jspx = anon
/member/jobapply.jspx = anon
/login.jspx = authc
/logout.jspx = logout
/member/** = user
/jeeadmin/jeecms/login.do = authc
/jeeadmin/jeecms/logout.do = logout
/jeeadmin/jeecms/** =user
</value>
</property>
</bean>
<!-- Shiro Filter -->
<!-- 全局定义adminLogin,adminPrefix 供下面的bean使用 -->
<bean id="adminUrlBean" class="com.jeecms.core.security.CmsAdminUrl">
<property name="adminLogin" value="/jeeadmin/jeecms/login.do" />
<property name="adminPrefix" value="/jeeadmin/jeecms/" />
</bean>
<!--
自定义过滤
parent="adminUrlBean" 继承adminUrlBean 注入的属性
-->
<bean id="authcFilter" class="com.jeecms.core.security.CmsAuthenticationFilter"
parent="adminUrlBean">
<!-- 登录成功后进入的页面 -->
<property name="adminIndex" value="/jeeadmin/jeecms/index.do" />
</bean> <!--
<entry key="user" value-ref="userFilter" /> 配置过滤 user 权限的访问地址
/member/** = user /jeeadmin/jeecms/** =user
-->
<bean id="userFilter" class="com.jeecms.core.security.CmsUserFilter"
parent="adminUrlBean" /> <!-- 退出过滤器 -->
<bean id="logoutFilter" class="com.jeecms.core.security.CmsLogoutFilter"
parent="adminUrlBean" /> <!-- 核心管理类 入口, security 安全,-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="shiroEhcacheManager" />
<property name="rememberMeManager" ref="rememberMeManager" />
<property name="realm" ref="authorizingRealm" /> <!-- 凭证匹配器 -->
</bean>
<!-- 凭证匹配器,核心验证登录与权限授权 -->
<bean id="authorizingRealm" class="com.jeecms.core.security.CmsAuthorizingRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 加密的方式,MD5 -->
<property name="hashAlgorithmName" value="MD5" />
<!-- true means hex encoded, false means base64 encoded -->
<property name="storedCredentialsHexEncoded" value="true" />
<!-- 迭代次数,散列的次数 ,加密的次数,2的话就是加密后把加密的值再加密一次 -->
<property name="hashIterations" value="1" />
</bean>
</property>
<property name="cmsUserMng" ref="cmsUserMng" />
</bean>
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!--
<property name="cacheManagerConfigFile">
<value>classpath:ehcache-shiro.xml</value> </property>
-->
<property name="cacheManager">
<ref local="cacheManager" />
</property>
</bean>
<!-- 会话Cookie模板 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--
constructor-arg 构造器注入
前端登录或后端登录,可以传入rememberMe 参数实现记住我功能
rememberMe是cookie的名字
-->
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="31536000" /><!-- 365天 -->
</bean>
<!--
rememberMe管理器
cipherKey是加密rememberMe Cookie的密钥;默认AES算法;
-->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
<property name="cookie" ref="rememberMeCookie" />
</bean>
<!--
Enable Shiro Annotations for Spring-configured beans. Only run after
-->
<!--
the lifecycleBeanProcessor has run:
jeecms-servlet-admin.xml中配置使用 lifecycleBeanPostProcessor Shiro生命周期处理器
LifecycleBeanPostProcessor用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调,
在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调。
如UserRealm就实现了Initializable,
而DefaultSecurityManager实现了Destroyable。
-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>

jeecmsv8 shiro 分析的更多相关文章

  1. spring boot整合shiro

    安全框架Shiro和Spring Security比较,本文主要围绕Shiro进行学习 一 Shiro 是一个强大而灵活的开源安全框架,能够清晰的处理认证 授权 管理会话以及,密码加密 01 .认证与 ...

  2. shiro550反序列化分析

    拖了很久的shiro分析 漏洞概述 Apache Shiro <= 1.2.4 版本中,加密的用户信息序列化后存储在Cookie的rememberMe字段中,攻击者可以使用Shiro的AES加密 ...

  3. Shiro源码分析-初始化-Realm

    在上一篇介绍SecurityManager的初始化过程中,也有realm的粗略介绍. realm的概念在安全领域随处可见: 各种中间件的realm.spring security的realm.shir ...

  4. Shiro 源码分析

    http://my.oschina.net/huangyong/blog/215153 Shiro 是一个非常优秀的开源项目,源码非常值得学习与研究. 我想尝试做一次 不一样 的源码分析:源码分析不再 ...

  5. shiro实现无状态的会话,带源码分析

    转载请在页首明显处注明作者与出处 朱小杰      http://www.cnblogs.com/zhuxiaojie/p/7809767.html 一:说明 在网上都找不到相关的信息,还是翻了大半天 ...

  6. Java安全(权限)框架 - Shiro 功能讲解 架构分析

    Java安全(权限)框架 - Shiro 功能讲解 架构分析 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 简述Shiro Shiro出自公司Apache(阿帕奇),是java的一 ...

  7. shiro过滤器详解分析

    (原) shiro最核心的2个操作,一个是登录的实现,一就是过滤器了.登录有时间再补录说明,这里分析下shiro过滤器怎样玩的. 1.目标 这里会按如下顺序逐一看其实原理,并尽量找出其出处. 先看一下 ...

  8. Apache Shiro Java反序列化漏洞分析

    1. 前言 最近工作上刚好碰到了这个漏洞,当时的漏洞环境是: shiro-core 1.2.4 commons-beanutils 1.9.1 最终利用ysoserial的CommonsBeanuti ...

  9. Shiro源码分析之SecurityManager对象获取

    目录 SecurityManager获取过程 1.SecurityManager接口介绍 2.SecurityManager实例化时序图 3.源码分析 4.总结 @   上篇文章Shiro源码分析之获 ...

随机推荐

  1. work-record:20190618

    ylbtech-work-record:20190618 1.返回顶部 1.1. -- formId记录表 -- select * from record_form_id; -- drop table ...

  2. iOS开发NSLayoutConstraint代码自动布局

    1.NSLayoutConstraint简介 适配界面大多用Masonry工具,也是基于NSLayoutConstraint写的!通过使用两个类方法实现自动布局: + (NSArray<__ki ...

  3. 初探JVM总结

    什么是JVM Java Virtual Machine(Java虚拟机)的缩写 .本质上是一个程序. java语言运行的平台,是ava跨平台的根本. java默认的三种类加载器 BootStrap C ...

  4. P3338 [ZJOI2014]力 /// FFT 公式转化翻转

    题目大意: https://www.luogu.org/problemnew/show/P3338 题解 #include <bits/stdc++.h> #define N 300005 ...

  5. VMware Workstation 10 简体中文安装教程

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 分享到 一键分享 QQ ...

  6. 使用CEfSharp之旅(7)CEFSharp 拦截 http 请求 websocket 内容

    原文:使用CEfSharp之旅(7)CEFSharp 拦截 http 请求 websocket 内容 版权声明:本文为博主原创文章,未经博主允许不得转载.可点击关注博主 ,不明白的进群19106581 ...

  7. CSRF spring mvc 跨站请求伪造防御(转)

    CSRF CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一 ...

  8. angular 级联选择

    HTML: <link rel="stylesheet" href="views/tree/checkbox.css"/> <div clas ...

  9. android-启动另外一个Activity

    启动另外一个Activity 在完成了上一节课的学习后,我们已经创建了一个带有text输入框和一个button的app. 在本课中,我们将在MainActivity类中添加SendButton的单击响 ...

  10. ThinkPHP引用第三方库

    Thinkphp引用第三方库的方法例如引用购物车:在项目Home目录下,新建一个文件夹(以下是我自己的demo) Tool文件夹,在Tool文件夹中创建Tool.class.php文件.这个和你控制器 ...