使用spring安全容器管理web程序
2013-01-10 23:29
585 查看
说明.ssh的不贴了 只有spring安全容器的 其他的不贴(目标 实现简单的管理)
spring的容器好处
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
:解决session伪造 跳跃访问 页面必须参数 方法权限等等
数据库 :基本的 用户表-资源表-角色表及相互之间的关联表
web.xml
<!-- spring的监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
applicationContext.xml
<?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:p="http://www.springframework.org/schema/p"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver">
</property>
<property name="jdbcUrl" value="jdbc:sqlserver://localhost:1433;databaseName=mydb">
</property>
<property name="user" value="sa"></property>
<property name="password" value="123456"></property>
</bean>
<!--不用添加到安全容器中去-->
<security:http pattern="/**/*.css" security="none"/>
<security:http pattern="/login.jsp*" security="none"/>
<security:http pattern="/admin/login.jsp*" security="none"/>
<security:http access-decision-manager-ref="myaccessDecisionManager">
<!-- 没用但是重要 否者不会执行我们自定义的myaccessDecisionManager-->
<security:intercept-url pattern="/**" access="ROLE_XXX" />
<!-- session失效去的页面, -->
<security:session-management invalid-session-url="/login.jsp"></security:session-management>
<!-- 登录页面为/login.jsp,登录成功页面为/index.jsp,且总是用这个页面为登录成功页面 -->
<security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" default-target-url="/index.jsp" always-use-default-target="true" />
</security:http>
<bean id="myaccessDecisionManager" class="com.spring.MyAccessDecisionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<security:authentication-manager>
<security:authentication-provider>
<!-- 查询用户和对应的权限。。 -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select u.username,u.password,u.status as enabled from users u where u.username=? "
authorities-by-username-query="select u.username, r.name as authority from dbo.user_role ur join dbo.users u
on u.id=ur.user_id join dbo.roles r on r.id=ur.role_id where u.username = ? " cache-ref="userCache"/>
</security:authentication-provider>
</security:authentication-manager>
<!--用户的缓存-->
<bean id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<property name="cache" ref="userEhCache"></property>
</bean>
<bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="userCache"></property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"></bean>
<!-- 消息提示 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:org/springframework/security/messages_zh_CN" />
</bean>
</beans>
上面的可以添加更多的东西 请参考官方的文档
自己定义的MyAccessDecisionManager类
package com.spring;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class MyAccessDecisionManager implements AccessDecisionManager{
private Logger logger = Logger.getLogger(MyAccessDecisionManager.class);
private ComboPooledDataSource dataSource;
public ComboPooledDataSource getDataSource() {
return dataSource;
}
public void setDataSource(ComboPooledDataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
InsufficientAuthenticationException {
//请求的url
logger.info("当前请求:"+object.toString() );
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
List<String> list_role= null;
//没有当前用户 --》跳跃访问
try {
userDetails =(UserDetails)obj;
} catch (Exception e) {
throw new AuthorizationServiceException("认证失败!");
}
Connection con =null;
PreparedStatement ps = null;
ResultSet set = null;
try {
con= dataSource.getConnection();
String sql = "select rl.name from resc_role rr join rescs re on rr.resc_id = re.id join roles rl on rr.role_id = rl.id where re.res_string = ? ";
//数据库查询对应的
ps= con.prepareStatement(sql);
System.out.println( "|"+ object.toString().substring( object.toString().indexOf("/") )+"|" );
ps.setString(1 , object.toString().substring( object.toString().indexOf("/") ) );
set = ps.executeQuery();
list_role = new ArrayList<String>();
while(set.next()){
list_role.add(set.getString("name") );
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
try {
if(set!=null)set.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(set!=null) ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(set!=null) con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (String string : list_role) {
//当前用户角色
for( GrantedAuthority g : userDetails.getAuthorities()){
if( g.getAuthority() .equals(string) ){
logger.info("您有权限!");
return;
}
}
}
throw new AccessDeniedException("呵呵!没有权限!");
}
@Override
public boolean supports(ConfigAttribute arg0) {
// TODO Auto-generated method stub
return true;//fan hui true
}
@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;//fanhui false
}
}
类说明: 其实可以使用hibernate的缓存解决查询问题 该类可以拿到请求的路径和当前用户相互判断 如果没有抛出没权限的异常 自己看来很多的文档觉得这个简单官方也推荐 最好不要改源码
bug:我个人没搞出来的就是使用两个登录的页面登录 现实中的肯定有的 我配置两个登录页面错误之后都跳到同一个页面 如果你解决了联系哦
参考
spring 3.1安全容器官方文档
spring的容器好处
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
:解决session伪造 跳跃访问 页面必须参数 方法权限等等
数据库 :基本的 用户表-资源表-角色表及相互之间的关联表
web.xml
<!-- spring的监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
applicationContext.xml
<?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:p="http://www.springframework.org/schema/p"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver">
</property>
<property name="jdbcUrl" value="jdbc:sqlserver://localhost:1433;databaseName=mydb">
</property>
<property name="user" value="sa"></property>
<property name="password" value="123456"></property>
</bean>
<!--不用添加到安全容器中去-->
<security:http pattern="/**/*.css" security="none"/>
<security:http pattern="/login.jsp*" security="none"/>
<security:http pattern="/admin/login.jsp*" security="none"/>
<security:http access-decision-manager-ref="myaccessDecisionManager">
<!-- 没用但是重要 否者不会执行我们自定义的myaccessDecisionManager-->
<security:intercept-url pattern="/**" access="ROLE_XXX" />
<!-- session失效去的页面, -->
<security:session-management invalid-session-url="/login.jsp"></security:session-management>
<!-- 登录页面为/login.jsp,登录成功页面为/index.jsp,且总是用这个页面为登录成功页面 -->
<security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" default-target-url="/index.jsp" always-use-default-target="true" />
</security:http>
<bean id="myaccessDecisionManager" class="com.spring.MyAccessDecisionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<security:authentication-manager>
<security:authentication-provider>
<!-- 查询用户和对应的权限。。 -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select u.username,u.password,u.status as enabled from users u where u.username=? "
authorities-by-username-query="select u.username, r.name as authority from dbo.user_role ur join dbo.users u
on u.id=ur.user_id join dbo.roles r on r.id=ur.role_id where u.username = ? " cache-ref="userCache"/>
</security:authentication-provider>
</security:authentication-manager>
<!--用户的缓存-->
<bean id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<property name="cache" ref="userEhCache"></property>
</bean>
<bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="userCache"></property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"></bean>
<!-- 消息提示 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:org/springframework/security/messages_zh_CN" />
</bean>
</beans>
上面的可以添加更多的东西 请参考官方的文档
自己定义的MyAccessDecisionManager类
package com.spring;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class MyAccessDecisionManager implements AccessDecisionManager{
private Logger logger = Logger.getLogger(MyAccessDecisionManager.class);
private ComboPooledDataSource dataSource;
public ComboPooledDataSource getDataSource() {
return dataSource;
}
public void setDataSource(ComboPooledDataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
InsufficientAuthenticationException {
//请求的url
logger.info("当前请求:"+object.toString() );
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
List<String> list_role= null;
//没有当前用户 --》跳跃访问
try {
userDetails =(UserDetails)obj;
} catch (Exception e) {
throw new AuthorizationServiceException("认证失败!");
}
Connection con =null;
PreparedStatement ps = null;
ResultSet set = null;
try {
con= dataSource.getConnection();
String sql = "select rl.name from resc_role rr join rescs re on rr.resc_id = re.id join roles rl on rr.role_id = rl.id where re.res_string = ? ";
//数据库查询对应的
ps= con.prepareStatement(sql);
System.out.println( "|"+ object.toString().substring( object.toString().indexOf("/") )+"|" );
ps.setString(1 , object.toString().substring( object.toString().indexOf("/") ) );
set = ps.executeQuery();
list_role = new ArrayList<String>();
while(set.next()){
list_role.add(set.getString("name") );
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
try {
if(set!=null)set.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(set!=null) ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(set!=null) con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (String string : list_role) {
//当前用户角色
for( GrantedAuthority g : userDetails.getAuthorities()){
if( g.getAuthority() .equals(string) ){
logger.info("您有权限!");
return;
}
}
}
throw new AccessDeniedException("呵呵!没有权限!");
}
@Override
public boolean supports(ConfigAttribute arg0) {
// TODO Auto-generated method stub
return true;//fan hui true
}
@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;//fanhui false
}
}
类说明: 其实可以使用hibernate的缓存解决查询问题 该类可以拿到请求的路径和当前用户相互判断 如果没有抛出没权限的异常 自己看来很多的文档觉得这个简单官方也推荐 最好不要改源码
bug:我个人没搞出来的就是使用两个登录的页面登录 现实中的肯定有的 我配置两个登录页面错误之后都跳到同一个页面 如果你解决了联系哦
参考
spring 3.1安全容器官方文档
相关文章推荐
- 在 Web 容器中使用 Spring + CXF 发布 WS(二) --SOAP 及其安全控制
- 使用Session State快速、可扩展、安全的管理Web程序(一)
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
- 使用Spring容器管理JavaBean
- 使用spring容器管理和配置netty
- 使用spring容器管理和配置netty4
- 简单使用Spring注解 测试程序 非web程序
- 使用spring实现事务管理(@transactional)的遇到的两个异常:java.lang.noclassdeffounderror:org/objectweb.asm
- Spring安全权限管理(Spring Security的配置使用)
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean - fjdingsd
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
- 基于纯Java代码的Spring容器和Web容器零配置的思考和实现(1) - 数据源与事务管理
- 使用 spring 容器管理 Filter
- 使用spring容器管理和配置netty
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
- 使用 Spring 容器管理 Filter
- Java 使用 Spring 容器管理 Servlet
- 使用spring等框架的web程序在Tomcat下的启动顺序及思路理清
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
- 【备忘】Filter由容器管理,想交给spring管理,需用代理 org.springframework.web.filter.DelegatingFilterProxy