jeecmsv8 shiro 分析

本文详细解析Jeecms V8后台登录流程及权限验证机制,包括登录页面配置、Shiro框架集成、自定义过滤器实现及错误处理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

源代码注释可见 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> 

转载于:https://www.cnblogs.com/Jeely/p/11214558.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值