项目结构:
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 3 <display-name>S3S2H3</display-name> 4 <!-- 设置log4j存放Log文件位置(通过spring统一进行管理) --> 5 <context-param> 6 <param-name>webAppRootKey</param-name> 7 <param-value>log.root</param-value> 8 </context-param> 9 10 <!-- 加载log4j的配置文件 --> 11 <context-param> 12 <param-name>log4jConfigLocation</param-name> 13 <param-value>classpath:log4j.properties</param-value> 14 </context-param> 15 <!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond--> 16 <context-param> 17 <param-name>log4jRefreshInterval</param-name> 18 <param-value>60000</param-value> 19 </context-param> 20 21 <context-param> 22 <param-name>contextConfigLocation</param-name> 23 <param-value>classpath*:applicationContext.xml,classpath:dao.xml,classpath:applicationContext-security.xml</param-value> 24 </context-param> 25 <!-- 为spring容器进行实例化 --> 26 <listener> 27 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 28 </listener> 29 <!-- <listener> --> 30 <!-- <listener-class>cn.com.sengis.service.listeners.SessionListener</listener-class> --> 31 <!-- </listener> --> 32 <!-- session的监听 --> 33 <listener> 34 <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 35 </listener> 36 <filter> 37 <filter-name>OpenSessionInViewFilter</filter-name> 38 <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> 39 </filter> 40 <filter-mapping> 41 <filter-name>OpenSessionInViewFilter</filter-name> 42 <url-pattern>/*</url-pattern> 43 </filter-mapping> 44 <!-- 权限 --> 45 <filter> 46 <filter-name>springSecurityFilterChain</filter-name> 47 <filter-class> 48 org.springframework.web.filter.DelegatingFilterProxy 49 </filter-class> 50 </filter> 51 <filter-mapping> 52 <filter-name>springSecurityFilterChain</filter-name> 53 <url-pattern>/*</url-pattern> 54 </filter-mapping> 55 56 <filter> 57 <filter-name>struts2</filter-name> 58 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 59 </filter> 60 <!-- <filter> --> 61 <!-- <filter-name>encodingFilter</filter-name> --> 62 <!-- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> --> 63 <!-- <init-param> --> 64 <!-- <param-name>encoding</param-name> --> 65 <!-- <param-value>UTF-8</param-value> --> 66 <!-- </init-param> --> 67 <!-- </filter> --> 68 <!-- <filter-mapping> --> 69 <!-- <filter-name>encodingFilter</filter-name> --> 70 <!-- <url-pattern>/*</url-pattern> --> 71 <!-- </filter-mapping> --> 72 <filter-mapping> 73 <filter-name>struts2</filter-name> 74 <url-pattern>*.action</url-pattern> 75 </filter-mapping> 76 77 78 <!-- DWR配置 --> 79 <servlet> 80 <servlet-name>dwr-invoker</servlet-name> 81 <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class> 82 <init-param> 83 <param-name>debug</param-name> 84 <param-value>true</param-value> 85 </init-param> 86 <init-param> 87 <param-name>crossDomainSessionSecurity</param-name> 88 <param-value>false</param-value> 89 </init-param> 90 <init-param> 91 <param-name>allowScriptTagRemoting</param-name> 92 <param-value>true</param-value> 93 </init-param> 94 <init-param> 95 <description>使用服务器推技术(反转AJAX)</description> 96 <param-name>activeReverseAjaxEnabled</param-name> 97 <param-value>true</param-value> 98 </init-param> 99 <init-param> 100 <param-name> 101 initApplicationScopeCreatorsAtStartup 102 </param-name> 103 <param-value>true</param-value> 104 </init-param> 105 <init-param> 106 <param-name>maxWaitAfterWrite</param-name> 107 <param-value>100</param-value> 108 </init-param> 109 <load-on-startup>4</load-on-startup> 110 </servlet> 111 <servlet-mapping> 112 <servlet-name>dwr-invoker</servlet-name> 113 <url-pattern>/dwr/*</url-pattern> 114 </servlet-mapping> 115 116 <!-- Spring刷新Interceptor防止内存泄漏 --> 117 <listener> 118 <listener-class> 119 org.springframework.web.util.IntrospectorCleanupListener 120 </listener-class> 121 </listener> 122 <welcome-file-list> 123 <welcome-file>index.html</welcome-file> 124 <welcome-file>index.htm</welcome-file> 125 <welcome-file>index.jsp</welcome-file> 126 <welcome-file>default.html</welcome-file> 127 <welcome-file>default.htm</welcome-file> 128 <welcome-file>default.jsp</welcome-file> 129 </welcome-file-list> 130 </web-app>
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xmlns:tx="http://www.springframework.org/schema/tx" 7 xmlns:p="http://www.springframework.org/schema/p" 8 xmlns:context="http://www.springframework.org/schema/context" 9 xsi:schemaLocation=" 10 http://www.springframework.org/schema/beans 11 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 12 http://www.springframework.org/schema/tx 13 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 14 http://www.springframework.org/schema/context 15 http://www.springframework.org/schema/context/spring-context-3.0.xsd 16 http://www.springframework.org/schema/aop 17 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 18 http://www.directwebremoting.org/schema/spring-dwr 19 http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd "> 20 <!-- 配置项不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能 --> 21 <context:annotation-config /> 22 <context:component-scan base-package="cn.com.sengis" /> 23 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 24 <property name="locations"> 25 <list> 26 <value>classpath:jdbc.properties</value> 27 </list> 28 </property> 29 </bean> 30 31 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 32 <property name="driverClass" value="${connection.driver_class}"></property> 33 <property name="jdbcUrl" value="${connection.url}"></property> 34 <property name="user" value="${connection.username}"></property> 35 <property name="password" value="${connection.password}"></property> 36 <!-- 指定连接池的最大连接数 --> 37 <property name="maxPoolSize" value="${proxool.maximum.connection.count}"></property> 38 <property name="minPoolSize" value="${proxool.minimum.connection.count}"></property> 39 <!-- 指定连接数据库连接池的初始化连接数 --> 40 <property name="initialPoolSize" value="${proxool.initialPoolSize}"></property> 41 <!-- 指定连接数据库连接池的最大连接时间 --> 42 <property name="maxIdleTime" value="${proxool.maxIdleTime}"></property> 43 </bean> 44 45 <!-- 定义Hibernate的sessionFactory,通过该Bean,可以获得Hibernate的Session--> 46 <bean id="sessionFactory" 47 class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 48 <property name="dataSource"> 49 <ref bean="dataSource" /> 50 </property> 51 <property name="hibernateProperties"> 52 <props> 53 <!--org.hibernate.dialect.MySQLInnoDBDialect --> 54 <prop key="hibernate.dialect"> 55 org.hibernate.dialect.MySQL5Dialect 56 </prop> 57 <!-- 是否根据需要创建数据库 --> 58 <prop key="hibernate.hbm2ddl.auto">update</prop> 59 <!--设置显示Hibernate操作的SQL语句--> 60 <prop key="hibernate.show_sql">true</prop> 61 <!-- 将sql脚本格式化后输出 --> 62 <prop key="hibernate.format_sql">true</prop> 63 <!--设置二级缓冲--> 64 <!--<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> --> 65 <!--设置二级缓冲,打开查询缓冲--> 66 <!--<prop key="hibernate.cache.use_query_cache">true</prop> --> 67 </props> 68 </property> 69 <!-- 映射文件配置 --> 70 <property name="mappingResources"> 71 <list> 72 <value>cn/com/sengis/bean/Student.hbm.xml</value> 73 <value>cn/com/sengis/bean/Resources.hbm.xml</value> 74 <value>cn/com/sengis/bean/Roles.hbm.xml</value> 75 <value>cn/com/sengis/bean/Users.hbm.xml</value> 76 </list> 77 </property> 78 </bean> 79 <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 80 <property name="sessionFactory"> 81 <ref local="sessionFactory"/> 82 </property> 83 </bean> 84 <tx:annotation-driven transaction-manager="transactionManager" /> 85 <!-- 配置事务增强处理Bean,指定事务管理器 --> 86 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 87 <!-- 用于配置详细的事务语义 --> 88 <tx:attributes> 89 <!-- 所有以'get'开头的方法是read-only的 --> 90 <tx:method name="get*" read-only="true"/> 91 <!-- 其他方法使用默认的事务设置 --> 92 <tx:method name="*" rollback-for="java.lang.Exception" propagation="REQUIRED"/> 93 </tx:attributes> 94 </tx:advice> 95 96 97 <aop:config> 98 <!-- 配置一个切入点,在匹配条件下应用事务 99 两个Bean的所有方法的执行 --> 100 <aop:pointcut id="pointcut" 101 expression="execution(* cn.com.sengis.service.*.*(..))"/> 102 <!-- 指定在pointcut切入点应用txAdvice事务增强处理 --> 103 <aop:advisor advice-ref="txAdvice" 104 pointcut-ref="pointcut"/> 105 </aop:config> 106 107 <bean id="myServiceBean" class="cn.com.sengis.service.ServiceBean"></bean> 108 <bean id="myAction" class="cn.com.sengis.action.MyAction"> 109 <property name="serviceBean"> 110 <ref bean="myServiceBean"/> 111 </property> 112 </bean> 113 114 <!-- 整合DWR --> 115 116 <!-- 方法一 --> 117 <!-- *********************************************************************** --> 118 <!-- <dwr:configuration> --> 119 <!-- <dwr:convert type="bean" class="com.lhq.User" /> --> 120 <!-- <dwr:convert type="bean" class="org.directwebremoting.ScriptSession" /> --> 121 <!-- </dwr:configuration> --> 122 123 124 <!-- <bean id="sayHello" class="cn.com.sengis.service.SayHello"> --> 125 <!-- <dwr:remote javascript="sayHello"> --> 126 <!-- <dwr:include method="sayHello" /> --> 127 <!-- </dwr:remote> --> 128 <!-- </bean> --> 129 <!-- <bean id="ChatManager" class="com.lhq.ChatManager"> --> 130 <!-- <dwr:remote javascript="ChatManager"> --> 131 <!-- <dwr:include method="updateUsersList"/> --> 132 <!-- <dwr:include method="setScriptSessionFlag"/> --> 133 <!-- <dwr:include method="getScriptSession"/> --> 134 <!-- <dwr:include method="send"/> --> 135 <!-- </dwr:remote> --> 136 <!-- </bean> --> 137 <!-- *********************************************************************** --> 138 139 <!-- 方法二(注解的方式) --> 140 <dwr:configuration> 141 <dwr:convert type="bean" class="cn.com.sengis.service.User" /> 142 <dwr:convert type="bean" class="org.directwebremoting.ScriptSession" /> 143 </dwr:configuration> 144 <dwr:annotation-scan base-package="cn.com.sengis" scanDataTransferObject="true" scanRemoteProxy="true" /> 145 146 147 148 149 150 </beans>
dao.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- 指定Spring配置文件的Schema信息 --> <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true"> <!-- 配置DAO组件的模板 --> <bean id="daoTemplate" abstract="true" p:sessionFactory-ref="sessionFactory"/> <bean id="hibernateDao" class="cn.com.sengis.dao.impl.HibernateDaoImpl" parent="daoTemplate"></bean> <bean id="usersDao" class="cn.com.sengis.dao.impl.UsersDaoImpl" parent="daoTemplate"></bean> <bean id="resourcesDao" class="cn.com.sengis.dao.impl.ResourcesDaoImpl" parent="daoTemplate"></bean> <bean id="rolesDao" class="cn.com.sengis.dao.impl.RolesDaoImpl" parent="daoTemplate"></bean> </beans>
applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="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/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <debug/> <!-- <global-method-security> --> <!-- Element 这个元素用来在你的应用程序中启用基于安全的注解(通过在这个元素中设置响应的属性), --> <!-- 也可以用来声明将要应用在你的实体application context中的安全切点组。 --> <!-- <global-method-security secured-annotations="enabled" jsr250-annotations="enabled"/> --> <!-- protect-pointcut是非常强大的,它让你可以用简单的声明对多个bean的进行安全声明。 参考下面的例子: Java代码 --> <!-- <global-method-security> --> <!-- <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))" access="ROLE_USER"/> --> <!-- </global-method-security> 这样会保护application context中的符合条件的bean的所有方法 --> <!-- 不要过滤图片等静态资源,其中**代表可以跨越目录,*不可以跨越目录。 --> <!-- <intercept-url pattern="/**/*.jpg" filters="none" /> --> <!-- <intercept-url pattern="/**/*.png" filters="none" /> --> <!-- <intercept-url pattern="/**/*.gif" filters="none" /> --> <!-- <intercept-url pattern="/**/*.css" filters="none" /> --> <!-- <intercept-url pattern="/**/*.js" filters="none" /> --> <!-- 这些请求不用过滤 --> <http pattern="/**/*.js" security="none"/> <http pattern="/**/*.css" security="none"/> <http pattern="/**/*.gif**" security="none"></http> <http pattern="/**/*.jpg" security="none"/> <http pattern="/login.jsp" security="none"/> <http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/a.jsp"> <logout invalidate-session="false" logout-success-url="/login.jsp" logout-url="/j_spring_security_logout"/> <!-- 实现免登陆验证 --> <!-- "记住我"功能,采用持久化策略(将用户的登录信息存放在数据库表中) --> <!-- <remember-me data-source-ref="dataSource" /> --> <remember-me /> <!-- session-management是针对session的管理. 这里可以不配置. 如有需求可以配置. --> <!-- id登陆唯一. 后登陆的账号会挤掉第一次登陆的账号 error-if-maximum-exceeded="true" 禁止2次登陆; session-fixation-protection="none" 防止伪造sessionid攻击. 用户登录成功后会销毁用户当前的session. 创建新的session,并把用户信息复制到新session中. --> <session-management invalid-session-url="/timeout.jsp"> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.jsp"></concurrency-control> </session-management> <!-- 定制自己的过滤器 --> <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" /> <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </http> <!-- 登录验证器 --> <beans:bean id="loginFilter" class="cn.com.sengis.security.MyUsernamePasswordAuthenticationFilter"> <!-- 处理登录 --> <beans:property name="filterProcessesUrl" value="/j_spring_security_check"></beans:property> <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property> <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property> <beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property> <beans:property name="usersDao" ref="usersDao"></beans:property> </beans:bean> <beans:bean id="loginLogAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> <!-- 登录成功后的页面 --> <beans:property name="defaultTargetUrl" value="/index.jsp"></beans:property> </beans:bean> <beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property> </beans:bean> <!-- 认证过滤器 --> <beans:bean id="securityFilter" class="cn.com.sengis.security.MySecurityFilter"> <!-- 用户拥有的权限 --> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <!-- 用户是否拥有所请求资源的权限 --> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <!-- 资源与权限对应关系 --> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean> <!-- 实现了UserDetailsService的Bean --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="myUserDetailServiceImpl"> <!-- <password-encoder ref="passwordEncoder"> --> <!-- <salt-source user-property="username"/> --> <!-- </password-encoder> --> </authentication-provider> </authentication-manager> <beans:bean id="myAccessDecisionManager" class="cn.com.sengis.security.MyAccessDecisionManager"></beans:bean> <beans:bean id="mySecurityMetadataSource" class="cn.com.sengis.security.MySecurityMetadataSource"> <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg> </beans:bean> <beans:bean id="myUserDetailServiceImpl" class="cn.com.sengis.security.MyUserDetailServiceImpl"> <beans:property name="usersDao" ref="usersDao"></beans:property> </beans:bean> <!-- 未登录的切入点 --> <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/login.jsp"></beans:property> </beans:bean> </beans:beans>
jdbc.properties
connection.driver_class=com.mysql.jdbc.Driver connection.url=jdbc:mysql://localhost:3306/spring_security?useUnicode=true&characterEncoding=UTF-8 connection.username=root connection.password=1234 proxool.maximum.connection.count=100 proxool.minimum.connection.count=5 proxool.initialPoolSize=1 proxool.maxIdleTime=200
log4j.properties
# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
log4j.rootLogger=INFO, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=${petstore.root}/WEB-INF/petstore.log
log4j.appender.logfile.MaxFileSize=512KB
# Keep three backup files.
log4j.appender.logfile.MaxBackupIndex=3
# Pattern to output: date priority [category] - message
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> <constant name="struts.i18n.encoding" value="utf-8"/> <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。 如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 --> <constant name="struts.action.extension" value="action"/> <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 --> <constant name="struts.serve.static.browserCache" value="false"/> <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 --> <constant name="struts.configuration.xml.reload" value="true"/> <!-- 开发模式下使用,这样可以打印出更详细的错误信息 --> <constant name="struts.devMode" value="true" /> <!-- struts的action交由spring创建和管理 --> <constant name="struts.objectFactory" value="spring" /> <package name="stu" namespace="/stu" extends="struts-default"> <action name="mystu" class="cn.com.sengis.action.MyAction"> <result name="success">/success.jsp</result> </action> </package> <package name="test" namespace="" extends="struts-default"> <action name="notice" class="cn.com.sengis.action.noticeAction"> <result>/noticeList.jsp</result> <result name="input">/noticeList.jsp</result> </action> <action name="test" class="cn.com.sengis.action.TestAction"> <result></result> </action> </package> </struts>
sql:
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `enable` int(11) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `account` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; CREATE TABLE `roles` ( `id` int(11) NOT NULL AUTO_INCREMENT, `enable` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; CREATE TABLE `resources` ( `id` int(11) NOT NULL AUTO_INCREMENT, `url` varchar(255) DEFAULT NULL, `priority` int(11) DEFAULT NULL, `type` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `memo` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; CREATE TABLE `roles_resources` ( `rsid` int(11) NOT NULL, `rid` int(11) NOT NULL, PRIMARY KEY (`rsid`,`rid`), KEY `FKAF06BF234B9B2DA4` (`rid`), KEY `FKAF06BF23B726B61B` (`rsid`), CONSTRAINT `FKAF06BF234B9B2DA4` FOREIGN KEY (`rid`) REFERENCES `roles` (`id`), CONSTRAINT `FKAF06BF23B726B61B` FOREIGN KEY (`rsid`) REFERENCES `resources` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `users_roles` ( `rid` int(11) NOT NULL, `uid` int(11) NOT NULL, PRIMARY KEY (`uid`,`rid`), KEY `FKF6CCD9C64BC73832` (`uid`), KEY `FKF6CCD9C64B9B2DA4` (`rid`), CONSTRAINT `FKF6CCD9C64B9B2DA4` FOREIGN KEY (`rid`) REFERENCES `roles` (`id`), CONSTRAINT `FKF6CCD9C64BC73832` FOREIGN KEY (`uid`) REFERENCES `users` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
演示截图