`

Shiro基于Spring的实现

阅读更多

参考:

http://kdboy.iteye.com/blog/1103794

http://blog.csdn.net/hxpjava1/article/details/7035724

http://blog.itpub.net/23071790/viewspace-709367/

http://www.infoq.com/cn/articles/apache-shiro

org.apache.shiro.spring.web.ShiroFilterFactoryBean DOC

 

在web.xml中配置Shiro的过滤器

 

<filter>
	<filter-name>shiroFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
	<filter-name>shiroFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>

 可以在<filter></filter>中加入targetFilterLifecycle

 

 

<init-param>
	<param-name>targetFilterLifecycle</param-name>
	<param-value>true</param-value>
</init-param>

如果设置"targetFilterLifecycle"为true,则spring来管理Filter.init()和Filter.destroy();若为false,则这两个方法失效。

 

在Spring的配置文件中添加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="/wellcome" />
	<property name="unauthorizedUrl" value="/forbid" />
	<property name="filterChainDefinitions">
		<value>
			/login = authc
			/logout = logout
			/account/** = user
			/admin/** = authcBasic
		</value>
	</property>
</bean>

 这个时候就遇到一个问题,Shiro过滤器都是干什么用的?

anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic
org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms
org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port
org.apache.shiro.web.filter.authz.PortFilter
rest
org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles
org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter

 

写道
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里的?后面的参数。
perms:例子/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于
isPermitedAll()方法。
roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证才能使用,没有参数
authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

这些过滤器分为两组,一组是认证过滤器,一组是授权过滤器。其中anon,authcBasic,auchc,user是第一组,
perms,roles,ssl,rest,port是第二组
authcBasic就是弹出一个登录窗口,要求用户输入用户名和密码。适合于对安全性要求不高的系统或设备中,如大家所用路由器的配置页面的认证

还有就是自定义过滤器了,举个官方的例子

 

 <bean id="myCustomFilter" class="com.class.that.implements.javax.servlet.Filter"/>
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="filterChainDefinitions">
        <value>
            /some/path/** = authc, myCustomFilter
        </value>
    </property>
 </bean>

  

在Spring的配置文件中添加securityManager和realm,加了个ehcache

 

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<property name="realm" ref="shiroDbRealm" />
	<property name="cacheManager" ref="shiroEhcacheManager" />
</bean>
<bean id="shiroDbRealm" class="com.**.ShiroDbRealm">
	<property name="accountService" ref="accountService"/>
</bean>
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
	<property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
</bean>

 

ehcache的配置

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<ehcache updateCheck="false" name="shiroCache">
	<!-- http://ehcache.org/ehcache.xml -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />
</ehcache>

 

 

又加上了AOP的权限控制和生命周期的配置

 

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

<!-- AOP式方法级权限检查  -->
<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>

 

以上已经将配置的东西都弄完了,好像很简单的样子

配置完成就是Java的一些实现了,先说Realm

public class ShiroDbRealm extends AuthorizingRealm {

	protected AccountService accountService;

	/**
	 * 认证回调函数,登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = accountService.findUserByLoginId(token.getUsername());
		if (user != null) {
			if ("disabled".equals(user.getStatus())) {
				throw new DisabledAccountException();
			}

			byte[] salt = Encodes.decodeHex(user.getSalt());
			return new SimpleAuthenticationInfo(new ShiroUser(user.getLoginId(), user.getName()), user.getPassword(),
					ByteSource.Util.bytes(salt), getName());
		} else {
			return null;
		}
	}

	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
		User user = accountService.findUserByLoginId(shiroUser.loginName);
		if (user != null) {
			Hibernates.initLazyProperty(user.getRoles());
		}
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		for (Role role : user.getRoles()) {
			// 基于Role的权限信息
			info.addRole(role.getName());
			// 基于Permission的权限信息
			info.addStringPermissions(role.getPermissionList());
		}
		return info;
	}

	/**
	 * 设定Password校验的Hash算法与迭代次数.
	 */
	@PostConstruct
	public void initCredentialsMatcher() {
		HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(AccountService.HASH_ALGORITHM);
		matcher.setHashIterations(AccountService.HASH_INTERATIONS);

		setCredentialsMatcher(matcher);
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}
}

 自定义了一个ShiroUser,目的是为了保存更多的用户信息

/**
 * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息.
 */
public static class ShiroUser implements Serializable {
	private static final long serialVersionUID = -1373760761780840081L;
	public String loginName;
	public String name;

	public ShiroUser(String loginName, String name) {
		this.loginName = loginName;
		this.name = name;
	}

	public String getName() {
		return name;
	}

	/**
	 * 本函数输出将作为默认的<shiro:principal/>输出.
	 */
	@Override
	public String toString() {
		return loginName;
	}

	/**
	 * 重载hashCode,只计算loginName;
	 */
	@Override
	public int hashCode() {
		return Objects.hashCode(loginName);
	}

	/**
	 * 重载equals,只计算loginName;
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		ShiroUser other = (ShiroUser) obj;
		if (loginName == null) {
			if (other.loginName != null) {
				return false;
			}
		} else if (!loginName.equals(other.loginName)) {
			return false;
		}
		return true;
	}
}

 建了两个PO,user,role

public class User implements Serializable {

	private Long id;
	private String loginId;
	private String password;
	private String salt;
	private String name;
	private String email;
	private Integer status;
	private List<Role> roles = Lists.newArrayList();

	... get/set...
}

 

public class Role implements Serializable {

	private Long id;
	private String name;
	private String permissions;

	...get/set...

	public List<String> getPermissionList() {
		return ImmutableList.copyOf(StringUtils.split(permissions, ","));
	}
}

 OK。其他的就是登录页面和Controller了,这个就不说了。

分享到:
评论
1 楼 eastseven 2015-01-07  
good

相关推荐

    shiro+spring的Demo

    - **Spring配置Shiro**:通过Spring的Bean定义来配置Shiro,如定义 Realm 实现,将认证和授权逻辑注入到Spring的上下文中。 - **AOP集成**:利用Spring的AOP功能,可以在方法执行前/后进行权限检查,实现细粒度的...

    shiro整合spring项目实例

    在本项目实例中,我们将深入探讨如何将Shiro与Spring框架整合,以实现更高效、灵活的安全控制。 1. **Shiro基础** Apache Shiro 提供了用户认证、权限授权、加密和会话管理四大核心功能。认证是指验证用户身份,...

    spring cloud + shiro集成方案

    手把手教你集成spring cloud + shiro微服务...用最少的工作量,改造基于shiro安全框架的微服务项目,实现spring cloud + shiro 框架集成。博客地址:https://blog.csdn.net/weixin_42686388/article/details/103084289

    cas+shiro+spring实例

    这个实例是专为初学者设计的,旨在帮助他们理解和实现基于CAS的单点登录(Single Sign-On, SSO)系统,同时结合Shiro进行权限管理和认证。下面我们将详细探讨这些技术以及它们如何协同工作。 **CAS (Central ...

    Shiro+Spring Security学习文档

    2. **过滤器链**:Spring Security基于Servlet Filter实现,通过配置过滤器链,可以实现请求级别的安全控制。 3. **认证与授权**:Spring Security支持多种认证方式,如Basic Auth、Form Login、Remember Me等,...

    基于spring redis的shiro session共享

    但是该套实现,代码质量非常差(10几个java文件,都快吓晕),并且redis的连接没有基于spring,而是在java代码中硬编码,这几乎无法容忍。 为此,本人基于spring连接redis,吸取了他们文章的思想,重新写了一套解决...

    shiro+spring集成

    - **用户认证**:Shiro 提供了多种认证方式,如基于表单的身份验证、记住我功能等。 - **权限控制**:通过角色和权限设置,实现对 URL 或方法的访问控制。 - **会话管理**:Shiro 可以管理和监控用户的会话,支持...

    ShiroSpring

    - Shiro可与Spring Session集成,实现分布式会话管理,特别适用于微服务架构。 7. **安全最佳实践**: - 使用强密码策略,包括长度限制、字符组合和定期更换。 - 为敏感操作启用CSRF防护。 - 对敏感数据进行...

    springcloud-shiro

    在这个项目中,我们看到"springcloud-shiro"是一个基于Spring Boot的Shiro实现,其中还应用了Spring Cloud的相关组件,特别是Zuul作为边缘服务进行API网关路由。 Shiro是一个强大且易用的Java安全框架,提供了认证...

    Shiro和Spring整合 这个资源真的可运行

    1. **松耦合**:Shiro 可以独立于 Spring 使用,但整合后,可以通过 Spring 的 DI 和 AOP 实现更灵活的配置和控制。 2. **统一管理**:整合后,Shiro 的安全控制可以与其他 Spring 组件一起管理,如事务、缓存等,...

    shiro与spring整合工程源代码

    将Shiro与Spring整合,可以充分利用两者的优点,实现更高效、更灵活的安全管理。 在"shiro与spring整合工程源代码"中,我们可以看到以下几个关键的知识点: 1. **Shiro的核心组件**: - **Authentication(认证)...

    shiro-spring.rar

    在"shiro-spring.rar"这个压缩包中,我们很显然看到了一个基于Maven构建的项目,它整合了Apache Shiro与Spring框架,但未包含Spring MVC部分。这意味着这是一个后端安全控制的实现,可能适用于RESTful API或传统的...

    spring boot+shiro 权限认证管理案例

    通过以上步骤,我们可以构建一个集成了 Spring Boot 和 Shiro 的权限认证管理系统,能够实现用户登录、权限校验、会话管理等功能,同时利用缓存提升系统性能。在实际开发中,还可以根据需求扩展 Shiro 功能,例如...

    shiro+spring mvc集成的实例源码

    5. **安全注解**:在 Spring MVC 控制器的方法上使用 Shiro 提供的注解(如 `@RequiresAuthentication`、`@RequiresRoles` 和 `@RequiresPermissions`),实现基于方法的权限控制。 6. **登录和登出处理**:编写...

    权限管理系统,基于 shiro,spring mvc,mybatis 框架开发

    总结来说,这个基于Shiro、Spring MVC和MyBatis的权限管理系统实现了从用户认证到资源访问控制的全过程,为企业级应用提供了安全的访问控制机制。通过学习和实践这个项目,开发者可以深入理解Java Web安全框架的应用...

    Spring Shiro 学习系统 Spring-Shiro-training

    Spring Shiro-training项目旨在提供一个综合的学习环境,帮助开发者理解和掌握如何在Spring应用中集成Apache Shiro框架,实现安全、高效的身份验证与授权。 Apache Shiro是一个强大且易用的Java安全框架,它处理了...

    spring boot+shiro+mybatis实现不同用户登录显示不同的权限菜单

    Spring Boot是基于Spring框架的快速开发工具,它简化了配置并提供了“开箱即用”的特性。在本项目中,Spring Boot用于搭建后端服务,包括数据库连接、RESTful API设计以及自动配置等。Spring Security可以作为Spring...

    spring+springMVC+shiro 完美例子

    总之,这个"spring+springMVC+shiro 完美例子"是一个很好的学习资源,帮助开发者深入理解如何在Java Web应用中集成和使用这些强大的框架,实现安全、高效的权限管理。通过分析和实践这个例子,开发者不仅可以提升...

    Spring Boot+Apache Shiro+Spring MVC+MyBatis+Quartz+Druid DEMO

    这是一个基于Spring Boot、Apache Shiro、Spring MVC、MyBatis、Quartz和Druid的数据源管理框架的示例项目,名为"renren-security"。这个DEMO提供了完整的权限管理和任务调度解决方案,下面是这些技术栈的核心知识点...

    shiro实现单点登录

    2. **Spring Session Data Redis**:基于Spring Session项目,利用Redis存储用户会话,实现跨服务器的会话共享。这对于分布式系统中的SSO至关重要,因为用户登录状态需要在所有应用之间同步。 集成步骤如下: 1. **...

Global site tag (gtag.js) - Google Analytics