shiro与spring整合详解与spring项目中shiro注解不生效的解决办法
2017-10-25 09:25
946 查看
一、spring项目中的shiro配置
(1)web.xml配置
<!-- shiro过滤器 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <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>
(2)shiro与spring整合配置
<!-- 使用shiro安全检查注解 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean>
<!-- shiro的生命周期处理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- shiro自带的密码匹配器(用来校验密码足够了) --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.SimpleCredentialsMatcher"></bean> <!-- security datasource: --> <bean id="myRealm" class="cc.eguid.service.shiro.MyRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"/><!-- 密码匹配器 --> <property name="cachingEnabled" value="false"/><!-- 禁止缓存 --> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> </bean> <!-- shiro过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 配置安全管理器 --> <property name="securityManager" ref="securityManager" /> <!-- 身份认证失败跳转的地址 --> <property name="loginUrl" value="/login/" /> <!-- 身份认证成功跳转的地址 --> <property name="successUrl" value="/" /> <!-- 权限认证失败跳转的地址 --> <property name="unauthorizedUrl" value="/login/unauthorized" /> <property name="filterChainDefinitions"> <!--anon 表示匿名访问,不需要认证以及授权 --> <!--authc表示需要认证 没有进行身份认证是不能进行访问的 --> <!--authc,roles[admin]表示是admin角色的用户才能访问 --> <value> /static/** = anon /login/** = anon /common/** = anon /admin/** = authc,roles[admin] /* = authc /** = authc </value> </property> </bean>
二、realm和自定义密码校验器实现
1、realm实现
public class MyRealm extends AuthorizingRealm{ Logger log=Logger.getLogger(MyRealm.class); @Autowired private UserService userService;//这是自己实现的用户信息操作类,实现用户信息,用户角色信息、用户权限信息查询功能 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { UserInfo user = (UserInfo) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 查询角色信息 Collection<String> roles = userService.findRoles(user); info.addRoles(roles); log.info("shiro获取用户所属角色列表:"+roles); // 查询权限信息 Collection<String> permissions = userService.findPermissions(user.getSystemuserid()); info.addStringPermissions(permissions); log.info("shiro获取用户权限列表:"+permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{ //用户输入的用户名密码 String loginname= token.getPrincipal().toString(); Object password=token.getCredentials(); log.info("shiro正在处理尝试登录的用户信息:"+loginname+",密码:"+new String((char[])password)); //数据库中的用户信息 UserInfo user =userService.queryUserInfoByLoginName(loginname); if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){ return null; } log.info("shiro获取到当前用户尝试登录的真实数据:"+user.getLoginusername()+",密码:"+user.getPassword()); //数据库中的正确的账户信息 AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName()); //自己获取密码验证器(由于shiro实现的密码校验方法是密码错误会直接抛异常,不采用,所以改成直接手动校验) CredentialsMatcher matcher=getCredentialsMatcher(); if(matcher==null){ log.error("没有配置密码匹配器"); return null; } //校验密码 if(matcher.doCredentialsMatch(token,accountInfo)){ return accountInfo;//校验通过,返回账号信息 } return null; } }
2、自定义密码校验器
/** * 自定义shiro密码匹配(密码是在md5散列值的基础上再次进行md5加盐操作,加盐值不保存在数据库,而是放在配置文件中) * @author eguid * */ public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher { private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class); protected Object getCredentials(AuthenticationToken token) { return token.getCredentials(); } protected Object getCredentials(AuthenticationInfo info) { return info.getCredentials(); } @Autowired private CommonConfigs commonConfigs; /** * 验证密码 * * @param tokenCredentials * @param accountCredentials * @return */ protected boolean equals(Object tokenCredentials, Object accountCredentials) { if (log.isDebugEnabled()) { log.debug("Performing credentials equality check for tokenCredentials of type [" + tokenCredentials.getClass().getName() + " and accountCredentials of type [" + accountCredentials.getClass().getName() + "]"); } if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) { if (log.isDebugEnabled()) { log.debug("Both credentials arguments can be easily converted to byte arrays. Performing " + "array equals comparison"); } byte[] tokenBytes = toBytes(tokenCredentials); byte[] accountBytes = toBytes(accountCredentials); return MessageDigest.isEqual(tokenBytes, accountBytes); } else { return accountCredentials.equals(tokenCredentials); } } public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { Object tokenCredentials = getCredentials(token); Object accountCredentials = getCredentials(info); String account=String.valueOf((char[])tokenCredentials); if(commonConfigs.getMd5salt()==null){ if (log.isDebugEnabled()) { log.debug("配置文件中的加盐值为空,无法进行密码匹配,请确认配置文件是否在指定位置或配置指定加盐值"); } return false; } String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt()); if (log.isDebugEnabled()) { log.debug("加盐后的密码:"+saltaccount); } return equals(accountCredentials, saltaccount.toCharArray()); } }
三、注解使用及模板标签使用(其中注解无效)
1、注解使用
@RequiresPermissions({"user:update:view"})//检查操作权限@RequiresPermissions(value={"user:add","user:view"},logical=Logical.OR)//两个操作权限其中一个满足条件即可通过检查
@RequiresRoles({"admin"})//检查角色
@RequiresRoles(value={"debug","admin"},logical=Logical.OR)//两个角色其中一个角色满足条件即可
@RequiresAuthentication//检查是否通过shiro认证
@RequiresGuest//不需要验证
@RequiresUser//检查用户是否是当前系统中的用户
2、标签使用
使用标签需要先导入shiro的标签库<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>(1)显示用户身份信息
<shiro: principal/>默认调用Subject.getPrincipal()获取
<shiro:principal property="username"/>
相当于((User)Subject.getPrincipals()).getUsername()
(2)已登录shiro用户显示
<shiro:user>欢迎[<shiro:principal/>]登录,<a href="logout">退出</a>
<shiro:user>
(3)匿名用户访问
<shiro:guest>未经过shiro验证的用户(游客,匿名用户)</shiro:guest>(4)已经在shiro登录过的(已登录用户)
<shiro:authenticated>用户[<shiro:principal/>]已身份验证通过
<shiro:authenticated>
(5)没有在shiro登录过的
<shiro:notAuthenticated>未身份验证(包括记住我)
<shiro:notAuthenticated>
(6)检查角色
<shiro:hasRole name="admin">用户[<shiro:principal/>]拥有角色admin<br/>
<shiro:hasRole>
检查任意角色(其中一个满足条件即通过,相当于OR)
<shiro:hasAnyRoles name="admin,user">
用户[<shiro:principal/>]拥有角色admin或user<br/>
<shiro:hasAnyRoles>
不具有角色(反向判断)
<shiro:lacksRole name="abc">
用户[<shiro:principal/>]不具有角色abc<br/>
<shiro:lacksRole>
(7)操作权限判断
<shiro:hasPermission name="user:create">用户[<shiro:principal/>]拥有权限user:create<br/>
<shiro:hasPermission>
不具有操作权限(反向判断)
<shiro:lacksPermission name="org:create">
用户[<shiro:principal/>]没有权限org:create<br/>
<iro:lacksPermission>
四、注解不生效解决办法
把shiro注解放到springMVC的注解扫描之后(即放在springMVC容器中加载)<!-- 使用shiro安全检查注解 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean>把上面的shiro直接扫描放到下面的servlet-context.xml中即可让shiro注解生效
<!-- springMVC应用 --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/servlet-context.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
相关文章推荐
- Mybatis整合Spring3,事务注解为何不起作用的解决办法
- shiro和Spring整合使用注解时没有执行realm的doGetAuthorizationInfo回调方法的解决
- shiro和Spring整合使用注解时没有执行realm的doGetAuthorizationInfo回调方法的解决
- Spring boot项目中自定义的controller不生效的解决办法
- 【Spring】spring-mvc hibernate druid jdbc等数据源事务配置详解(解决注解事务不生效问题)
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- Spring 全注解配置 bean 和 调用 (8) @Aspect注解不生效解决办法 和 no-static 的警告解决办法
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 详解git中配置的.gitignore不生效的解决办法
- SSH整合项目修改字段不成功但页面可以跳转解决办法
- Spring mvc+struts2+Hibernate整合实例代码(注解详解)
- ssh项目整合shiro时,在struts2的action中使用shiro的注解进行权限控制时,NoSuchMethodException:com.sun.proxy.$Proxy26
- Spring MVC @Transactional注解方式事务失效的解决办法
- Spring 整合Redis 出现 afterPropertiesSet signature: ()V) Incompatible argument to function 解决办法
- struts2.2.1+spring 3.0.3+hibernate3.6+dwr3.0全注解整合详解
- 访问linux环境下的spring boot项目需要用户名和密码的解决办法
- 009-shiro与spring web项目整合【三】验证码、记住我