集成SSH和SpringSecurity

来源:互联网 发布:linux 代码格式化工具 编辑:程序博客网 时间:2024/04/29 23:53

呃,工作并不是我想的那么好找,去深圳二十天,面试了六家,第一天三家把我累吐血,在外面坐车转地铁走路六个多小时,三家面试加起来没超过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处理登陆成功的

@Componentpublic 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对象是吧,先来看看上面还实现的一个类

@Componentpublic 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
@Componentpublic 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经过来给它设置属性

@Componentpublic 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;    }}

嗯。整合完了。以后忘了也可以自己看看

0 0
原创粉丝点击