`

Spring3与安全框架apache shiro的整合

阅读更多

 shiro是一个很不错的安全框架,相对Spring security 来说要简单易用的多,使用shiro来做web的权限子系统是不错的选择。

 

下面记录一下shiro和Spring整合的过程:

 

 

<?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.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<description>Shiro 配置</description>
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login.jsp" />
		<property name="successUrl" value="/index.jsp" />
		<property name="unauthorizedUrl" value="/login.do" />
		<property name="filterChainDefinitions">
			<value>
				/login.jsp = anon
				/login.do = anon
				/** = authc
               </value>
		</property>
	</bean>

	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<!--设置自定义realm-->
		<property name="realm" ref="monitorRealm" />
	</bean>

	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
	
	<!--自定义Realm 继承自AuthorizingRealm-->
	<bean id="monitorRealm" class="***module.system.security.MonitorRealm"></bean>
	<!-- securityManager -->
	<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod"
			value="org.apache.shiro.SecurityUtils.setSecurityManager" />
		<property name="arguments" ref="securityManager" />
	</bean>
	
	<!-- Enable Shiro Annotations for Spring-configured beans.  Only run after -->
	<!-- the lifecycleBeanProcessor has run: -->
	<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>
</beans>

 

 

将shiro的配置文件引入到web.xml中:

 

 

 

并在web.xml中加入如下代码:

 

 

 

 

<!-- Shiro Security filter -->
	<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>*.do</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

 

实现自己的Realm

 

@Service("monitorRealm")
public class MonitorRealm extends AuthorizingRealm {
	
	@Autowired UserService userService;
	@Autowired RoleService roleService;
	@Autowired LoginLogService loginLogService;
	
	public MonitorRealm(){
		super();

	}
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		/*这里编写授权代码*/
		
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
	/*这里编写认证代码*/
	}
	
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

}

 

登录时的代码示例:

 

Subject currentUser = SecurityUtils.getSubject();
        if(!currentUser.isAuthenticated()){
        	UsernamePasswordToken token;
            if(null == rememberMe)
            	token = new UsernamePasswordToken(user.getUsername(), EncryptUtils.encodeMD5String(user.getPassword()),false,request.getRemoteAddr());
            else token = new UsernamePasswordToken(user.getUsername(), EncryptUtils.encodeMD5String(user.getPassword()), true, request.getRemoteAddr());
            try {
            	currentUser.login(token);
            } catch ( AuthenticationException ae ) {
            	request.setAttribute("message", "用户名或密码错误!");
            	return "login";
            }
        }

 执行currentUser.login(token);这句代码时,shiro会自动调用用户实现的Realm的doGetAuthenticationInfo进行身份认证。

登出时的代码示例:

 

Subject currentUser = SecurityUtils.getSubject();
        if (currentUser != null) {
        	currentUser.logout();
        }
        HttpSession session = request.getSession(false);
        if( session != null ) {
            session.invalidate();
        }
		return "login";

 在对用户(角色)进行授权时会执行Realm里的doGetAuthorizationInfo方法。

 

OK简单的集成完成了,如果用cas或者Springsecurity恐怕没这么简单利索 哈哈。

 

还有其他的细节,注解、授权、安全标签等等 以后再贴吧。

 

补贴个图吧,公司安全做的太恶心,代码考不出来。



 

 

  • 大小: 164.2 KB
分享到:
评论
5 楼 cjdxlgb 2013-11-08  
引用
111
4 楼 shenbai 2013-01-16  
alyouge 写道
请问登录时候是怎么验证的  currentUser.login(token);   怎么和我数据库里的用户关联!


写到这里doGetAuthenticationInfo()
使用jdbc、hibernate操作呀,验证成后new一个SimpleAuthenticationInfo 并返回就可以了,不成功则直接返回一个null。
登录时先通过SecurityUtils.getSubject();
获取到subject,然后用用subject.isAuthenticated()进行判断。
3 楼 alyouge 2012-12-29  
请问登录时候是怎么验证的  currentUser.login(token);   怎么和我数据库里的用户关联!
2 楼 jazzmozart 2012-06-25  
gxz1989611 写道
登录时的代码示例中的rememberMe没有定义啊?!

可选的
1 楼 gxz1989611 2012-06-11  
登录时的代码示例中的rememberMe没有定义啊?!

相关推荐

Global site tag (gtag.js) - Google Analytics