集成SSH和SpringSecurity
Posted z8z87878
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集成SSH和SpringSecurity相关的知识,希望对你有一定的参考价值。
呃,工作并不是我想的那么好找,去深圳二十天,面试了六家,第一天三家把我累吐血,在外面坐车转地铁走路六个多小时,三家面试加起来没超过15分钟,一家培训机构,一家说我没工作经验,HR拿我凑人数,一家给两千在深圳….第四家我没把握好,第五家等了三个小时九个人群面…第六家尼玛把我气回来了。面试质量太差了。怪我不会写简历,第四家没把握好,没在深圳坚持下来吧。找工作真不简单.南昌校招没几家公司,过段时间可能会去杭州,唉。乘着这一个月学习了下javaee的那些常见框架,以后也可以找android和java后台的工作
转载请声明出处:由http://blog.csdn.net/z8z87878转载
这里就不讲导包了,那么多…..缺包报错也能找,其中Structs2它是集成Spring的,为什么这么说呢,因为它有一个Structs2-Spring-puling插件jar包,所以Spring文件中不用配它,就是要注意Structs2引用的class不是单例的,是原型,所以需要把控制类标记为原型的。好的,开始配置吧。先配置web.xml文件
<!-- Spring的监听器,监听服务的生命周期来管理bean -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- SpringSecurity相关,需要配置在Structs2的拦截器前面,由它来负责登陆权限控制 -->
<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>
<!-- Structs2相关,配置核心拦截器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- 默认不拦截转发,这里修改成拦截,为后面集成SpringSecurity -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
然后再classpath下即src下创建ApplicationContext.xml配置文件,因为我们要再里面集成Hibernate,所以我们先完成Hibernate的自身配置。在src下创建db.properties配置连接数据库的属性
jdbc.user=root(账号)
jdbc.password=123456(密码)
jdbc.driverClass=com.mysql.jdbc.Driver(数据库对应的驱动)
jdbc.jdbcUrl=jdbc:mysql:///dbName(///后的是数据库名)
然后再在src下创建hibernate.cfg.xml配置常规属性(建议装Hibernate和Spring的插件,就不用自己找dtd和Schme依赖了)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 方言 -->
<property name="hibernate.hbm2ddl.auto">update</property> <!-- 表的生成策略 -->
<property name="hibernate.show_sql">true</property> <!-- 控制台打印SQL -->
<property name="hibernate.format_sql">true</property>
<!-- 二级缓存相关 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.use_query_cache">true</property>
</session-factory>
</hibernate-configuration>
好,Hibernate的准备工作就这样做好了,来进入Spring的配置文件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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 自动扫描包 -->
<context:component-scan base-package="com.ee.ems"></context:component-scan>
<!-- 文件中要用到刚才配置的连接数据库信息,这里把它导进来,分开配置好管理 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源,用到刚才配置的连接数据库信息 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="$jdbc.user"></property>
<property name="password" value="$jdbc.password"></property>
<property name="driverClass" value="$jdbc.driverClass"></property>
<property name="jdbcUrl" value="$jdbc.jdbcUrl"></property>
</bean>
<!-- 配置Hibernate的session管理工厂 ,它依赖于上面的数据源dataSource ref引用 -->
<bean id="sessionFactoryBean" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 导入刚才配置的hibernate基本属性, classpath表示src目录下 -->
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
<!-- 这表示导入实体类根据Hibernate生成的xml文件(有插件比较好,自动生成自己改点就好了) -->
<property name="mappingLocations" value="classpath:com/ee/ems/entities/*.hbm.xml"></property>
</bean>
<!-- 配置事务管理器 它依赖于上面配置的session管理工厂 。。所以一个依赖一个,记着这三个的关系就好配了 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryBean"></property>
</bean>
<!-- 事务扫描版,它的value值默认是上面配得transactionManager,所有可以省掉不写 -->
<tx:annotation-driven/>
</beans>
好了,到这里SSH就配好了,额Structs2.xml没有是吧,额,它的源码包有一个最简单的blank例子,整合也跟它没什么关系我觉得…它是靠那个插件包struts2-spring-plugin-2.3.15.3.jar跟spring连在一起的。嗯,好了。接下来来集成SpringShecurity,我们前面已经在web.xml中配置了SpringShecurity的拦截器。现在在src目录下建ApplicationContext-security.xml。只要是ApplicationContext*.xml格式的就行,因为前面配置web.xml配置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:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- http协议,自动配置一些熟悉 -->
<security:http auto-config="true">
<!--登陆相关配置 -->
<!-- login-page指定登陆页面 -->
<!-- username-parameter登陆页面表达中对应用户名密码的字段 -->
<!-- login-processing-url登陆处理交给SpringSecurity来做 值对应表单action=security-login-->
<!-- authentication-success-handler-ref登陆成功由实现了AuthenticationSuccessHandler接口的类来处理,这个我们自己实现由Spring扫描拿到引用 ,弄完配置进去看-->
<security:form-login
login-page="/index.jsp"
username-parameter="loginName"
password-parameter="password"
login-processing-url="/security-login"
authentication-failure-handler-ref="myAuthenticationFailHandlerRef"
authentication-success-handler-ref="myAuthenticationSuccessHandlerRef"
/>
<!-- 同上理, invalidate-session默认即为true让session失效,所以不用写-->
<security:logout
logout-url="同上理"
success-handler-ref="同上理"
invalidate-session="true"
/>
</security:http>
<!-- 权限管理配置 -->
<security:authentication-manager>
<!--user-service-ref指向实现了UserDetailsService接口的类的对象的引用,这里赋予user各个属性来处理后面的登陆和权限管理,等下进去看 -->
<security:authentication-provider user-service-ref="myUserDetailsService">
<!-- 密码采用md5加密方式,由用户名作为加盐处理,注意,这里的user-property参数一定是username无论你表单是loginName还是什么 -->
<security:password-encoder hash="md5">
<security:salt-source user-property="username"/>
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
</beans>
好,上面配置文件讲到两个自己实现的类,先来看MyAuthenticationSuccessHandlerRef处理登陆成功的
@Component
public class MyAuthenticationSuccessHandlerRef implements AuthenticationSuccessHandler
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication arg2) throws IOException,
ServletException
// TODO Auto-generated method stub
System.out.println("success");
request.getRequestDispatcher("/login").forward(request, response);
看名字就知道,成功后调用到原先Struct2的登陆处理,因为我这是后面集成的,也可以自己根据逻辑处理,到这可能回想如何拿到登陆的user对象是吧,先来看看上面还实现的一个类
@Component
public class MyUserDetailsService implements UserDetailsService
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException
// TODO Auto-generated method stub
System.out.println(username);
String password="3dd8cce415a5983df873a809003dedb3"; //从数据库中查(模拟的正确密码z8z87878账号zdmina md5加盐处理后,下面main就是)
boolean enabled=true;//是否可用
boolean accountNonExpired = true; //账户没有过期
boolean credentialsNonExpired = true;//凭证没有过期
boolean accountNonLocked = true;//账户没有被锁定
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new GrantedAuthorityImpl("ROLE_ADMIN")); //权限必须以ROLE开头,这也应该从数据库中查
MySecurityUser user = new MySecurityUser(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
Employee employee = new Employee();
employee.setLoginName(username);
employee.setPassword(password);
user.setEmployee(employee);
//返回user对象,然后SpringSecurity将根据这个来判断你是不是能登陆
return user;
public class MySecurityUser extends User
private Employee employee;
public Employee getEmployee()
return employee;
public void setEmployee(Employee employee)
this.employee = employee;
public MySecurityUser(String username, String password,
boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities)
super(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);
// TODO Auto-generated constructor stub
//SpringSecurity的根据用户名md5加盐处理加密.帮助我们模拟数据
public static void main(String[] args)
Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
String encodePassword = md5PasswordEncoder.encodePassword("z8z87878", "admina");
System.out.println(encodePassword);
好了,上面我们根据数据空中存储的用户密码,权限等属性来构造user去判断能否登陆。登陆成功后我们可以通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()来获取user对象。
到这里,好像我们只用到了密码,并没有用到权限authentication对吧,权限是不能然我们随便访问哪个页面的,所以我们需要去配置权限 ,权限我们不能在xml文件中静态配置,我们需要根据数据库中存储的页面路径和权限对应表来设置,这里动态设置SpringSecurity的FilterSecurityInterceptor类对象的SecurityMetadataSource来设置url和权限的对应关系.我们先来准备SecurityMetadataSource
@Component
public class MyFilterInvocationSecurityMetadataSource implements FactoryBean<DefaultFilterInvocationSecurityMetadataSource>
@Override
public DefaultFilterInvocationSecurityMetadataSource getObject()
throws Exception
// TODO Auto-generated method stub
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
//模拟从数据库中查询出
RequestMatcher requestMatcher = new AntPathRequestMatcher("/list.jsp");
Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
configAttributes.add(new SecurityConfig("ROLE_ADMIN")); //模拟,这里可能对应不止这一个权限,当然也不止这一个路径
requestMap.put(requestMatcher, configAttributes);
DefaultFilterInvocationSecurityMetadataSource dfsms = new DefaultFilterInvocationSecurityMetadataSource(requestMap);
return dfsms;
@Override
public Class<?> getObjectType()
// TODO Auto-generated method stub
return DefaultFilterInvocationSecurityMetadataSource.class;
@Override
public boolean isSingleton()
// TODO Auto-generated method stub
return true;
准备好SecurityMetadataSource后,怎么把它装配到FilterSecurityInterceptor中呢,FilterSecurityInterceptor是服务启动时Spring自动加载的,Spring有一个BeanPostProcessor接口,只要实现了它,并把它加上注解交给Spring管理,那么当Spring加载其他类实例化它们的对象时,都会经过我们定义的这个类被Spring实例化好的对象,Spring优先实例化它,然后等着FilterSecurityInterceptor经过来给它设置属性
@Component
public class MyBeanProcessing implements BeanPostProcessor
private boolean isSet = false;
private FilterSecurityInterceptor filterSecurityInterceptor;
@Autowired
private MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;
//其它bean实例化好后,要经过这里
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException
// TODO Auto-generated method stub
if(arg0 instanceof FilterSecurityInterceptor)
this.filterSecurityInterceptor = (FilterSecurityInterceptor) arg0;
else if(arg0 instanceof MyFilterInvocationSecurityMetadataSource)
this.myFilterInvocationSecurityMetadataSource = (MyFilterInvocationSecurityMetadataSource) arg0;
if(!isSet && filterSecurityInterceptor != null && myFilterInvocationSecurityMetadataSource != null)
try
//改变熟悉 filterSecurityInterceptor.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource.getObject());
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
isSet = true;
return arg0;
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException
// TODO Auto-generated method stub
return arg0;
嗯。整合完了。以后忘了也可以自己看看
以上是关于集成SSH和SpringSecurity的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security (4.0.1) 与 AngularJS 的集成。每次用户输入无效凭据时都会弹出基本身份验证