您的位置:首页 > 编程语言 > Java开发

<Spring Security3>入门级详细配置

2013-06-07 19:07 344 查看

很早之前就听说了SpringSecurity,

但是一直没时间,最近花了几天时间试验了,感觉确实挺方便的。

研究过程中,虽然碰到了一些问题,但是最后还是解决了。

由于还没有研究源码,此篇文章入门使用。

我写这篇文章参考了

/article/3593125.html

这是我使用的表结构

表名:RESOURCE解释:资源表

备注:资源表

RESOURCE(资源表)

是否主键
字段名

字段描述

数据类型

长度

可空
约束

缺省值

备注


ID

id

INT(11)

11

TYPE

类型(URL,METHOD)

VARCHAR(50)

50


VALUE

URL

VARCHAR(50)

50


MODEL_NAME

模块名

VARCHAR(50)

50


PARENT_ID

父模块ID

VARCHAR(50)

50


表名:ROLE解释:角色表

备注:角色表

ROLE(角色表)

是否主键
字段名

字段描述

数据类型

长度

可空
约束

缺省值

备注


ID

id

INT(11)

11

NAME

角色名

VARCHAR(50)

50


DESCRIPTION

角色描述

VARCHAR(50)

50


表名:ROLE_RESOURCE解释:角色资源表

备注:角色资源表

ROLE_RESOURCE(角色资源表)

是否主键
字段名

字段描述

数据类型

长度

可空
约束

缺省值

备注

ROLE_ID

角色ID

VARCHAR(50)

50


RESOURCE_ID

资源ID

VARCHAR(50)

50


表名:USER解释:用户表

备注:用户表

USER(用户表)

是否主键
字段名

字段描述

数据类型

长度

可空
约束

缺省值

备注


NAME

用户名

VARCHAR(50)

50

PASSWORD

密码

VARCHAR(50)

50


DISABLED

是否有效

CHAR(1)

1


EMAIL

邮箱

VARCHAR(100)

100


表名:USER_ROLE解释:用户角色表

备注:用户角色表

USER_ROLE(用户角色表)

是否主键
字段名

字段描述

数据类型

长度

可空
约束

缺省值

备注

USER_ID

用户ID

VARCHAR(50)

50


ROLE_ID

角色ID

VARCHAR(50)

50


相关的jar包可到spring官网下载,我使用的是springsecurity3.1.3

下载链接:

http://repo.springsource.org/libs-release-local/org/springframework/security/spring-security/3.1.3.RELEASE/spring-security-3.1.3.RELEASE-dist.zip

首先web.xml配置

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/config/*.xml
</param-value>
</context-param>
<!--spring监听-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--SpringSecurity会话控制-->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<!--SpringsecurityFilter-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


这里主要做了三件事,

1、加载Spring;

2、加载SpringSecurity;

3、添加SpringSecuritySession监听器(用于控制登录)

SpringSecirty如下:

<?xmlversion="1.0"encoding="UTF-8"?>
<beans:beansxmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.1.xsd">
<debug/>

<global-method-securitypre-post-annotations="enabled"/>

<!--此目录下不需要过滤-->
<httppattern="/js/**"security="none"/>
<httppattern="/resources/**"security="none"/>
<httppattern="/css/**"security="none"/>
<httppattern="/dwr/**"security="none"/>
<httppattern="/images/**"security="none"/>
<httppattern="/login.jsp"security="none"/>

<httpuse-expressions="true">
<!--非匿名用户就允许访问-->
<intercept-urlpattern="/index.jsp"access="isAuthenticated()"/>
<form-loginlogin-page="/login.jsp"authentication-failure-url="/login.jsp?error=true"always-use-default-target="true"default-target-url="/index.jsp"/>
<logoutlogout-success-url="/login.jsp"/>
<!--没有权限访问的页面-->
<access-denied-handlererror-page="/403.jsp"/>
<session-management></session-management>
<remember-me/>
<custom-filterref="myFilter"before="FILTER_SECURITY_INTERCEPTOR"/>
</http>

<!--指定提示信息-->
<beans:beanid="messageSource"class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:propertyname="basename"value="classpath:spring-security"></beans:property>
</beans:bean>

<authentication-manageralias="myAuthenticationManager">
<authentication-providerref="authenticationProvider">
</authentication-provider>
</authentication-manager>

<beans:beanid="authenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:propertyname="userDetailsService"ref="userdetailService"/>
<!--显示用户错误信息-->
<beans:propertyname="hideUserNotFoundExceptions"value="false"/>
<beans:propertyname="passwordEncoder"ref="md5password"></beans:property>
</beans:bean>
<!--密码加密策略-->
<beans:beanname="md5password"class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"></beans:bean>

<beans:beanname="userdetailService"class="com.yindejin.system.MyAuthenticationManager">
<beans:propertyname="systemService"ref="systemService"></beans:property>
</beans:bean>

<beans:beanname="myFilter"class="com.yindejin.system.MySecurityFilter">
<!--用户拥有的权限-->
<beans:propertyname="authenticationManager"ref="myAuthenticationManager"/>
<!--用户是否拥有所请求资源的权限-->
<beans:propertyname="accessDecisionManager"ref="myAccessDecisionManager"/>
<!--资源与权限对应关系-->
<beans:propertyname="securityMetadataSource"ref="mySecurityMetadataSource"/>
</beans:bean>

<beans:beanid="myAccessDecisionManager"class="com.yindejin.system.MyAccessDecisionManager"></beans:bean>
<beans:beanid="mySecurityMetadataSource"class="com.yindejin.system.MySecurityMetadataSource">
<beans:constructor-argname="systemService"ref="systemService"></beans:constructor-arg>
</beans:bean>

</beans:beans>

<custom-filterref="myFilter"before="FILTER_SECURITY_INTERCEPTOR"/>

这里的FILTER_SECURITY_INTERCEPTOR是SpringSecurity过滤器链中默认的Filter,

他的主要功能是

1、校验用户名、密码;

2、初始化时一次性加载所有的资源角色信息

3、检查用户访问权限

我们自定义的Filter必须在它之前,由于我们自己的过滤器和默认过滤器功能是一样的,所以就替换掉了原来的过滤器。

接下来是myFilter几个关键类

MySecurityFilter

packagecom.yindejin.system;

importjava.io.IOException;

importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;

importorg.springframework.security.access.SecurityMetadataSource;
importorg.springframework.security.access.intercept.AbstractSecurityInterceptor;
importorg.springframework.security.access.intercept.InterceptorStatusToken;
importorg.springframework.security.web.FilterInvocation;
importorg.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

publicclassMySecurityFilterextendsAbstractSecurityInterceptorimplementsFilter{
//与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,
//其他的两个组件,已经在AbstractSecurityInterceptor定义
privateFilterInvocationSecurityMetadataSourcesecurityMetadataSource;

@Override
publicSecurityMetadataSourceobtainSecurityMetadataSource(){
returnthis.securityMetadataSource;
}

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,
FilterChainchain)throwsIOException,ServletException{
FilterInvocationfi=newFilterInvocation(request,response,chain);
invoke(fi);
}

privatevoidinvoke(FilterInvocationfi)throwsIOException,ServletException{
System.out.println("用户发送请求!");
InterceptorStatusTokentoken=null;
token=super.beforeInvocation(fi);
try{
fi.getChain().doFilter(fi.getRequest(),fi.getResponse());
}finally{
super.afterInvocation(token,null);
}
}

publicFilterInvocationSecurityMetadataSourcegetSecurityMetadataSource(){
returnsecurityMetadataSource;
}

publicvoidsetSecurityMetadataSource(FilterInvocationSecurityMetadataSourcesecurityMetadataSource){
this.securityMetadataSource=securityMetadataSource;
}

publicvoidinit(FilterConfigarg0)throwsServletException{
//TODOAuto-generatedmethodstub
}

publicvoiddestroy(){
//TODOAuto-generatedmethodstub

}

@Override
publicClass<?extendsObject>getSecureObjectClass(){
//下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误
returnFilterInvocation.class;
}}


MySecurityMetadataSource

packagecom.yindejin.system;

importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.HashMap;
importjava.util.LinkedHashMap;
importjava.util.List;
importjava.util.Map;
importjava.util.Set;

importjavax.servlet.http.HttpServletRequest;

importorg.springframework.security.access.ConfigAttribute;
importorg.springframework.security.access.SecurityConfig;
importorg.springframework.security.web.FilterInvocation;
importorg.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
importorg.springframework.security.web.util.AntPathRequestMatcher;
importorg.springframework.security.web.util.RequestMatcher;

importcom.yindejin.system.service.ISystemService;
importcom.yindejin.vo.Resource;
importcom.yindejin.vo.Role;
importcom.yindejin.vo.User;

//1加载资源与权限的对应关系
publicclassMySecurityMetadataSourceimplementsFilterInvocationSecurityMetadataSource{
//由spring调用
publicMySecurityMetadataSource(ISystemServicesystemService){
this.systemService=systemService;
}

privateISystemServicesystemService;
publicISystemServicegetSystemService(){
returnsystemService;
}

publicvoidsetSystemService(ISystemServicesystemService){
this.systemService=systemService;
}

privatestaticLinkedHashMap<RequestMatcher,Collection<ConfigAttribute>>resourceMap=null;

publicCollection<ConfigAttribute>getAllConfigAttributes(){
//TODOAuto-generatedmethodstub
returnnull;
}

publicbooleansupports(Class<?>clazz){
//TODOAuto-generatedmethodstub
returntrue;
}
//加载所有资源与权限的关系
privateMap<String,String>getResource(){
Map<String,String>resourceMap=newHashMap<String,String>();
List<User>users=systemService.getAllUser();
for(Useruser:users){
for(Rolerole:user.getUserRoles()){
Set<Resource>resources=role.getRoleResources();
for(Resourceresource:resources){
Stringurl=resource.getValue();
if(!resourceMap.containsKey(url)){
resourceMap.put(url,role.getName());
}else{
StringroleName=resourceMap.get(url);
resourceMap.put(url,roleName+","+role.getName());
}
}
}
}
returnresourceMap;

}

privatevoidloadResourceDefine(){
resourceMap=newLinkedHashMap<RequestMatcher,Collection<ConfigAttribute>>();
Map<String,String>resource=getResource();
for(Map.Entry<String,String>entry:resource.entrySet()){
Collection<ConfigAttribute>configAttributes=newArrayList<ConfigAttribute>();
configAttributes.add(newSecurityConfig(entry.getValue()));
resourceMap.put(newAntPathRequestMatcher(entry.getKey()),configAttributes);
}

}

//返回所请求资源所需要的权限
publicCollection<ConfigAttribute>getAttributes(Objectobject)throwsIllegalArgumentException{

HttpServletRequestrequest=((FilterInvocation)object).getRequest();
if(null==resourceMap){
System.out.println("请求地址"+((FilterInvocation)object).getRequestUrl());
loadResourceDefine();
System.out.println("我需要的认证:"+resourceMap.toString());
}
for(Map.Entry<RequestMatcher,Collection<ConfigAttribute>>entry:resourceMap.entrySet()){
if(entry.getKey().matches(request)){
returnentry.getValue();
}
}
returnnull;
}

}


MyAccessDecisionManager

packagecom.yindejin.system;

importjava.util.Collection;
importjava.util.Iterator;

importorg.springframework.security.access.AccessDecisionManager;
importorg.springframework.security.access.AccessDeniedException;
importorg.springframework.security.access.ConfigAttribute;
importorg.springframework.security.authentication.InsufficientAuthenticationException;
importorg.springframework.security.core.Authentication;
importorg.springframework.security.core.GrantedAuthority;

//3
publicclassMyAccessDecisionManagerimplementsAccessDecisionManager{

publicvoiddecide(Authenticationauthentication,Objectobject,Collection<ConfigAttribute>configAttributes)throwsAccessDeniedException,InsufficientAuthenticationException{
if(configAttributes==null){
return;
}
//所请求的资源拥有的权限(一个资源对多个权限)
Iterator<ConfigAttribute>iterator=configAttributes.iterator();
while(iterator.hasNext()){
ConfigAttributeconfigAttribute=iterator.next();
//访问所请求资源所需要的权限
StringneedPermission=configAttribute.getAttribute();
System.out.println("needPermissionis"+needPermission);
//用户所拥有的权限authentication
for(GrantedAuthorityga:authentication.getAuthorities()){
if(needPermission.contains((ga.getAuthority()))){
return;
}
}
}
//没有权限让我们去捕捉
thrownewAccessDeniedException("没有权限访问!");
}

publicbooleansupports(ConfigAttributeattribute){
//TODOAuto-generatedmethodstub
returntrue;
}

publicbooleansupports(Class<?>clazz){
//TODOAuto-generatedmethodstub
returntrue;
}

}



MyAuthenticationManager

packagecom.yindejin.system;

importorg.springframework.security.core.userdetails.UserDetails;
importorg.springframework.security.core.userdetails.UserDetailsService;
importorg.springframework.security.core.userdetails.UsernameNotFoundException;

importcom.yindejin.system.service.ISystemService;
importcom.yindejin.util.StringUtils;
importcom.yindejin.vo.User;

publicclassMyAuthenticationManagerimplementsUserDetailsService{

privateISystemServicesystemService;

publicvoidsetSystemService(ISystemServicesystemService){
this.systemService=systemService;
}

@Override
publicUserDetailsloadUserByUsername(StringuserName)throwsUsernameNotFoundException{
if(!StringUtils.isEmpty(userName)){
thrownewUsernameNotFoundException("用户名不能为空!");
}
Useruser=systemService.loginByUserName(userName);
if(user==null){
thrownewUsernameNotFoundException("用户名或密码错误!");
}
returnuser;
}

}


User

packagecom.yindejin.vo;

importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.HashMap;
importjava.util.HashSet;
importjava.util.List;
importjava.util.Map;
importjava.util.Set;

importjavax.persistence.Transient;

importorg.springframework.security.core.GrantedAuthority;
importorg.springframework.security.core.authority.GrantedAuthorityImpl;
importorg.springframework.security.core.userdetails.UserDetails;

/**
*Userentity.@authorMyEclipsePersistenceTools
*/

publicclassUserimplementsUserDetails{

//Fields

privateIntegerid;
privateStringname;
privateStringpassword="123456";
privateIntegerdisabled=0;
privateStringemail;
publicStringgetEmail(){
returnemail;
}

publicvoidsetEmail(Stringemail){
this.email=email;
}

privateSet<Role>userRoles=newHashSet<Role>();
@Transient
privateMap<String,List<Resource>>roleResources;

//Constructors

publicIntegergetId(){
returnid;
}

publicvoidsetId(Integerid){
this.id=id;
}

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

publicStringgetPassword(){
returnpassword;
}

publicvoidsetPassword(Stringpassword){
this.password=password;
}

publicIntegergetDisabled(){
returndisabled;
}

publicvoidsetDisabled(Integerdisabled){
this.disabled=disabled;
}

publicSet<Role>getUserRoles(){
returnuserRoles;
}

publicvoidsetUserRoles(Set<Role>userRoles){
this.userRoles=userRoles;
}

/**defaultconstructor*/
publicUser(){
}

publicStringgetUsername(){
returnname;
}

publicbooleanisAccountNonExpired(){
returntrue;
}

publicbooleanisAccountNonLocked(){
returntrue;
}

publicbooleanisCredentialsNonExpired(){
returntrue;
}

publicbooleanisEnabled(){
returnthis.disabled==0?true:false;
}

/**
*@returntheroleResources
*/
publicMap<String,List<Resource>>getRoleResources(){
//initroleResourcesforthefirsttime
if(this.roleResources==null){
this.roleResources=newHashMap<String,List<Resource>>();

for(Rolerole:this.userRoles){
StringroleName=role.getName();
Set<Resource>resources=role.getRoleResources();
for(Resourceresource:resources){
Stringkey=roleName+"_"+resource.getType();
if(!this.roleResources.containsKey(key)){
this.roleResources.put(key,newArrayList<Resource>());
}
this.roleResources.get(key).add(resource);
}
}

}
returnthis.roleResources;
}

@SuppressWarnings("deprecation")
@Override
publicCollection<GrantedAuthority>getAuthorities(){
Set<GrantedAuthority>authSet=newHashSet<GrantedAuthority>();
for(Rolerole:getUserRoles()){
authSet.add(newGrantedAuthorityImpl(role.getName()));
}
returnauthSet;
}

}


结束语:

自己的第一篇博客,本人不才,还请大家指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: