Shiro的Web项目配置
来源:互联网 发布:魔扣少儿编程网址 编辑:程序博客网 时间:2024/06/05 02:10
Shiro的Web项目配置
一 shiro的学习
二 shiro的java客户端配置
三 关于权限的一些问题
一 shiro的学习
官网和张开涛博客
二 shiro的java客户端配置
1.在web.xml中配置shiro的过滤器
<!-- shiro 安全过滤器 --><!-- The filter-name matches name of a 'shiroFilter' bean inside --><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><async-supported>true</async-supported><init-param><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>同时在web.xml读取shiro的配置文件
2.在spring-shiro-web.xml中配置:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 为了获取adminPath的值 --><context:property-placeholder ignore-unresolvable="true" location="classpath*:/system.properties"/><!-- 配置安全管理中心,Shiro的主要业务层对象基于web的应用程序 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="userRealm"/></bean><!-- 自定义的过滤器,用来验证登陆 --><bean id="formAuthenticationCaptchaFilter" class="com.huaxia.shiro.FormAuthenticationCaptchaFilter"><property name="usernameParam" value="username"/><property name="passwordParam" value="password"/><property name="captchaParam" value="captcha"/><property name="loginUrl" value="${adminPath}/login"/></bean><!-- 自定义的过滤器 --><bean id="userFilter" class="com.huaxia.shiro.HuaXiaUserFilter"></bean><!-- Shiro的Web过滤器,在web.xml中配置的shiroFilter即指向此 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- 指定一个安全管理中心,用来验证用户能否登陆和相关权限 --><property name="securityManager" ref="securityManager"/><!-- 所有地址被重定向到该地址 --><property name="loginUrl" value="${adminPath}/login"/><!-- 用户登录成功后的页面地址 --><property name="successUrl" value="${adminPath}"/><!-- 过滤器链,在shiroFilter之前即开始执行 --><property name="filters"><util:map><entry key="authc" value-ref="formAuthenticationCaptchaFilter"/><entry key="user" value-ref="userFilter"/></util:map></property><!-- 配置地址对应的过滤器 --><property name="filterChainDefinitions"><value>${adminPath}/login = authc/** = user</value></property></bean><!-- 保证实现了Shiro内部lifecycle函数的bean执行 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!-- 下面两个bean是shiro官网推荐的配置 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true" /></bean><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean></beans>
其中UserRealm的实现如下:
package com.huaxia.shiro;import javax.annotation.PostConstruct;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.DisabledAccountException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.google.code.kaptcha.Constants;import com.huaxia.Constant;import com.huaxia.common.utils.security.Digests;import com.huaxia.common.utils.security.Encodes;import com.huaxia.user.entity.User;import com.huaxia.user.service.UserService;@Servicepublic class UserRealm extends AuthorizingRealm { private Logger logger = LoggerFactory.getLogger(UserRealm.class); @Autowired private UserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(userService.findRoles(username)); authorizationInfo.setStringPermissions(userService.findPermissions(username)); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordCaptchaToken captchaToken = (UsernamePasswordCaptchaToken) token; String username = String.valueOf(token.getPrincipal()); User user = userService.findByUsername(username,Constant.USER_DELFLAG); if(null != user && doCaptchValidate(captchaToken)) { if (Boolean.TRUE.equals(user.getLocked())) { throw new LockedAccountException(); //帐号锁定 } if(Constant.LOGIN_STATUS_N.equals(user.getLoginStatus())){ throw new DisabledAccountException(); } byte[] salt = Encodes.decodeHex(user.getSalt()); //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user.getUserName(), user.getPassword(), //密码 ByteSource.Util.bytes(salt), getName() //realm name ); //SecurityUtils.getSubject().getSession().setAttribute("user", user); SecurityUtils.getSubject().getSession().setAttribute("userId", user.getUserId()); userService.updateByLogin(user); return authenticationInfo; }else{ throw new UnknownAccountException(); } } protected boolean doCaptchValidate(UsernamePasswordCaptchaToken token){ String captcha = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); if(captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha())){ throw new CaptchaException("Code error"); } return true; } @PostConstruct public void initCredentialsMatcher() { HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(Digests.SHA1); matcher.setHashIterations(Constant.HASH_INTERATIONS); setCredentialsMatcher(matcher); } @Override public void clearCachedAuthorizationInfo(PrincipalCollection principals) { super.clearCachedAuthorizationInfo(principals); } @Override public void clearCachedAuthenticationInfo(PrincipalCollection principals) { super.clearCachedAuthenticationInfo(principals); } @Override public void clearCache(PrincipalCollection principals) { super.clearCache(principals); } public void clearAllCachedAuthorizationInfo() { getAuthorizationCache().clear(); } public void clearAllCachedAuthenticationInfo() { getAuthenticationCache().clear(); } public void clearAllCache() { clearAllCachedAuthenticationInfo(); clearAllCachedAuthorizationInfo(); }}其中formAuthenticationCaptchaFilter的实现如下:
package com.huaxia.shiro;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import org.apache.shiro.web.util.WebUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class FormAuthenticationCaptchaFilter extends FormAuthenticationFilter {private Logger logger = LoggerFactory.getLogger(FormAuthenticationCaptchaFilter.class);public static final String DEFAULT_CAPTCHA_PARAM = "captcha";private String captchaParam = DEFAULT_CAPTCHA_PARAM;public String getCaptchaParam() {return captchaParam;}public void setCaptchaParam(String captchaParam){this.captchaParam = captchaParam;}protected String getCaptcha(ServletRequest request) {return WebUtils.getCleanParam(request, getCaptchaParam());}protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {String username = getUsername(request) == null ? "" : getUsername(request);String password = getPassword(request) == null ? "" : getPassword(request);String captcha = getCaptcha(request) == null ? "" : getCaptcha(request);boolean rememberMe = isRememberMe(request);return new UsernamePasswordCaptchaToken(username,password.toCharArray(), rememberMe, captcha);}@Overrideprotected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {//issueSuccessRedirect(request, response);// we handled the success redirect directly, prevent the chain from continuing:HttpServletRequest httpServletRequest = (HttpServletRequest)request;HttpServletResponse httpServletResponse = (HttpServletResponse)response;if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))|| request.getParameter("ajax") == null) {// 不是ajax请求httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + this.getSuccessUrl());} else {httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + this.getSuccessUrl());}return false;}}其中HuaXiaUserFilter的实现如下:
package com.huaxia.shiro;import org.apache.shiro.web.filter.authc.UserFilter;import org.apache.shiro.web.filter.session.NoSessionCreationFilter;import org.apache.shiro.web.util.WebUtils;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletResponse;public class HuaXiaUserFilter extends UserFilter { @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { /*if(!"XMLHttpRequest".equalsIgnoreCase(WebUtils.toHttp(response).getHeader("X-Requested-With")) || request.getParameter("ajax") == null ){ this.saveRequestAndRedirectToLogin(request, response); }else{*/ HttpServletResponse res = WebUtils.toHttp(response); res.setHeader("sessionstatus","timeout"); //res.sendError(HttpServletResponse.SC_UNAUTHORIZED); /* }*/ this.saveRequestAndRedirectToLogin(request, response); return false; }}3.另外在Mvc的配置文件spring-mvc.xml中加入如下拦截器内容:
<aop:config proxy-target-class="true"></aop:config><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean>
三 关于权限的一些问题
1.shiro如何实现验证码?
关于shiro的验证码,使用的是google的kaptcha , 在web.xml中配置sevlet如下:
<servlet><servlet-name>ImageServlet</servlet-name><servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class></servlet><servlet-mapping><servlet-name>ImageServlet</servlet-name><url-pattern>/ImageServlet</url-pattern></servlet-mapping>
由于通常密码保存使用的是md5加密,同样的密码在md5后会产生相同的加密后字符串,如果有数据库的查看权限,那么看到相同的加密后字符串,很容易猜到是相同的密码。同时根据md5对照表(或者一些网站),能够找到密码。 如果密码在加上随机盐后再进行md5,那么同样的密码在md5后的字符串是不同的,就能够避免上面两个问题。总的来说增加了破解的难度。
3.通常情况下用户-角色-权限(资源)之间的关系
用户与角色多对多:一个用户可以拥有多个角色,一个角色可以被多个用户具有
角色与权限(资源,主要指菜单,按钮等)多对多:一个角色可以拥有多个权限,一个权限可以被多个角色拥有
3.1 在首页,通常根据用户查找角色,然后根据角色列出相关的菜单栏和相关按钮
3.2 在系统配置中:
用户配置:可以增删用户,也可以配置用户的多个角色
角色配置:可以配置一个角色的多个权限
权限配置:可以增删相关的资源(菜单或者按钮)
4.shiro授权的几种方式:
4.1 在代码体中:
if (currentUser.hasRole("admin"))
4.2 在方法上:
@RequiresPermissions(“account:create”)public void openAccount( Account acct )
4.3 在jsp页面上:
<shiro:hasPermission name=“users:manage”> <a href=“manageUsers.jsp”> </a> </shiro:hasPermission>
Shiro的官方文档整理的感觉差强人意,非常不明朗,需要结合张开涛的博客来看。有很多的地方需要学习,后续更新。
- Shiro的Web项目配置
- shiro学习:shiro整合SpringMVC的web项目
- shiro入门实战笔记(8)--Web项目Url配置
- java 权限管理工具shiro在java web项目中的配置
- shiro之web配置
- 7shiro安全框架、web项目的发布
- Shiro整合Web项目及整合后的开发
- web项目shiro与spring集成 maven依赖及web配置详解
- 我的shiro之旅: 五 shiro与普通web项目集成
- Shiro在Web.xml中shiroFilter的Mapping配置错误
- shiro项目启动报cache无效的配置异常错误
- shiro的配置学习
- 记录shiro的配置
- springboot + shiro的配置
- shiro的简单配置
- shiro的URL配置
- web项目的log4j配置
- web项目的log4j配置
- 用AJAX与后台进行交互
- 七层总结
- 高斯模糊算法
- 深入探究connect函数
- vector的复制
- Shiro的Web项目配置
- Leetcode题解
- ALSA架构简介
- 关键字之标识符
- Oracle——Run as能运行Debug as出错(跟tomcat无关)
- Java中的equals和hashCode方法详解
- 2017 计蒜之道 初赛 第六场
- Java swing单选按钮
- gdb调试多进程,多线程