Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个资源来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
不多说了,直接上代码,这里采用springmvc与springSecurity结合。
web.xml配置
web.xml中主要配置了springmvc与springSecurity,指定了配置文件applicationContext*.xml与applicationContext-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!--ContextLoaderListener监听器,会创建WebApplicationContext实现类 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <!-- springmvc配置 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 强制进行转码为utf8 --> <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring security配置 --> <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> </web-app>
springmvc的配置 applicationContext-servlet.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> <!-- 自动扫描Controller类 --> <context:component-scan base-package="com.xj.action"/> <!-- 定义视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean> <mvc:annotation-driven /> <mvc:default-servlet-handler/> <mvc:resources mapping="/asserts/**" location="/asserts/"/> </beans>
数据库连接配置 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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean id="propertyConfigurer" class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > <property name="location" value= "/WEB-INF/config.properties" /> </bean> <bean id="language" class="com.xj.util.Language" > <property name="location" value= "/WEB-INF/lang.properties" /> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}" /> <property name="jdbcUrl" value="${jdbc.jdbcUrl}" /> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> <property name="minPoolSize" value="${jdbc.minPoolSize}" /> <property name="maxPoolSize" value="${jdbc.maxPoolSize}" /> <property name="maxIdleTime" value="${jdbc.maxIdleTime}" /> <property name="acquireIncrement" value="${jdbc.acquireIncrement}" /> <property name="maxStatements" value="${jdbc.maxStatements}" /> <property name="initialPoolSize" value="${jdbc.initialPoolSize}" /> <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}" /> <property name="acquireRetryAttempts" value="${jdbc.acquireRetryAttempts}" /> <property name="breakAfterAcquireFailure" value="${jdbc.breakAfterAcquireFailure}" /> <property name="testConnectionOnCheckout" value="${jdbc.testConnectionOnCheckout}" /> </bean> <!-- 注册一个JDBC数据源事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- --> <!-- 基于@Transactional注解方式的事务管理 --> <tx:annotation-driven transaction-manager="txManager" /> <!-- 这里路径需要修改 --> <!-- 配置自动扫描组件 --> <context:component-scan base-package="com.xj.dao" /> <context:component-scan base-package="com.xj.security" /> <context:component-scan base-package="com.xj.service" /> </beans>
上述配置中,需要用到config.properties相关连接信息
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://localhost:3306/myhome?useUnicode=true&characterEncoding=utf-8 jdbc.user=root jdbc.password=123 jdbc.minPoolSize=10 jdbc.maxPoolSize=20 jdbc.maxIdleTime=60 jdbc.acquireIncrement=2 jdbc.maxStatements=0 jdbc.initialPoolSize=2 jdbc.idleConnectionTestPeriod=60 jdbc.acquireRetryAttempts=30 jdbc.breakAfterAcquireFailure=false jdbc.testConnectionOnCheckout=false
下面就开始重中之重了springSecurity的配置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.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <http pattern="/login" security="none" /> <http use-expressions="true" access-denied-page="/login" > <form-login login-page="/login" authentication-failure-url="/login" default-target-url="/main" /> <logout logout-success-url="/login" /> <session-management invalid-session-url="/login"> <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/> </session-management> <custom-filter ref="myfilter" before="FILTER_SECURITY_INTERCEPTOR" /> <remember-me /> <logout invalidate-session="true" logout-success-url="/login" logout-url="/j_spring_security_logout"/> </http> <!--一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性 --> <beans:bean id="myfilter" class="com.xj.security.FilterSecurityInterceptor"> <beans:property name="authenticationManager" ref="authenticationManager"/> <!-- 认证管理器 --> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <!-- 决策管理器 --> <beans:property name="securityMetadataSource" ref="securityMetadataSource"/> <!-- 安全元数据资源 --> </beans:bean> <authentication-manager alias="authenticationManager" > <authentication-provider ref="authenticationProvider"> </authentication-provider> </authentication-manager> <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <beans:property name="userDetailsService" ref="myUserDetailService" /> </beans:bean> <beans:bean id="myUserDetailService" class="com.xj.security.MyUserDetailService" /> <!-- 决策管理器 --> <beans:bean id="myAccessDecisionManager" class="com.xj.security.MyAccessDecisionManager"> </beans:bean> <!-- 资源管理器 --> <beans:bean id="securityMetadataSource" class="com.xj.security.MySecurityMetadataSource" ></beans:bean> </beans:beans>
自定义filter拦截器FilterSecurityInterceptor,该方法需要继承AbstractSecurityInterceptor,其中最主要的是doFilter方法。
package com.xj.security; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; //自定义过滤器 public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{ //安全元数据资源 private MySecurityMetadataSource securityMetadataSource; @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } //可以这里进行相关操作 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fileInvocation = new FilterInvocation(request, response, chain); InterceptorStatusToken interceptorStatusToken = this.beforeInvocation(fileInvocation); //校验访问的路径需要的角色等 fileInvocation.getChain().doFilter(request, response); this.afterInvocation(interceptorStatusToken, null); } @Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } public MySecurityMetadataSource getSecurityMetadataSource() { return securityMetadataSource; } public void setSecurityMetadataSource( MySecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; this.securityMetadataSource.refreshResource(); } }
由FilterSecurityInterceptor的配置可以看出,其需要认证管理器authenticationManager,决策管理器accessDecisionManager,资源管理器securityMetadataSource
认证管理器authenticationManager中,最主要的是UserDetailsService,该方法将用户的权限信息封装一个User放到spring的全局缓存SecurityContextHolder中,以备后面访问资源时使用
package com.xj.security; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.DisabledException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.xj.dao.CommonDao; //身份认证管理器 public class MyUserDetailService implements UserDetailsService{ @Autowired private CommonDao commonDao; @Override public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException { List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(); GrantedAuthority ga = null; String sql="select * from auth_user where username=?"; Map userMap = commonDao.queryForOne(sql, username); if(userMap==null||userMap.size()==0){ throw new UsernameNotFoundException("用户" + username + " 不存在"); } if(userMap.get("enabled").toString().equals("false")){ throw new DisabledException("用户" + username + " 被冻结"); } String password = userMap.get("password").toString(); String roleIds[] = ( (String)userMap.get("roleId")).split(","); sql = "select * from auth_role where id=?"; for(String roleId:roleIds){ Map roleMap = commonDao.queryForOne(sql, roleId); String rolename = (String)roleMap.get("rolename"); ga = new GrantedAuthorityImpl(rolename); grantedAuthorities.add(ga); } User user = new User(username, password, true, true, true, true, grantedAuthorities); return user; } }
资源管理器,需要继承FilterInvocationSecurityMetadataSource服务器启动时,即加载数据库的资源信息
package com.xj.security; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import com.xj.dao.CommonDao; //资源管理器(统计出要访问的资源需要的角色) public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource{ @Autowired private CommonDao commonDao; private Map<String, Collection<ConfigAttribute>> resourceMap=null; //从数据库加载资源 public Map loadSource(){ resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); String resource_sql="select * from auth_resource"; String role_sql="select * from auth_role"; List<Map> resources = commonDao.queryForList(resource_sql); List<Map> roles = commonDao.queryForList(role_sql); Map<String,String> roleMap = new HashMap<String,String>(); //对应了role表的map for(Map role:roles){ String id = role.get("id").toString(); String rolename = (String)role.get("rolename"); roleMap.put(id, rolename); } for(Map resource:resources){ Collection<ConfigAttribute> collection=new ArrayList<ConfigAttribute>(); String url_pattern = (String)resource.get("url_pattern"); String access_role = (String)resource.get("access_role"); String roleIds[] = access_role.split(","); for(String roleId:roleIds){ ConfigAttribute ca = new SecurityConfig(roleMap.get(roleId)); collection.add(ca); } resourceMap.put(url_pattern, collection); } return resourceMap; } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } //获取访问某一个url所需的角色 @Override public Collection<ConfigAttribute> getAttributes(Object arg0) throws IllegalArgumentException { String url =((FilterInvocation)arg0).getRequestUrl(); if(resourceMap==null){ System.out.println("无访问权限"); return null; } Collection<ConfigAttribute> collection = resourceMap.get(url); return collection; } @Override public boolean supports(Class<?> arg0) { return true; } /** * 刷新资源配置 */ public void refreshResource(){ loadSource(); } }
需要commonDao类,可以算是一个公共类了
package com.xj.dao; import javax.sql.DataSource; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.Map.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Repository; import com.xj.util.Logger; import com.xj.util.PageInfo; @Repository("commonDao") public class CommonDao { @Autowired DataSource dataSource; public int execUp(String sql, final String params[]) throws SQLException { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return jdbcTemplate.update(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { if (params != null) { for (int i = 0; i < params.length; i++) { ps.setString(i + 1, params[i]); } } } }); } public List<Properties> execSql(String sql, final String params[]) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { if (params != null) { for (int i = 0; i < params.length; i++) { ps.setString(i + 1, params[i]); } } } }, new ItemMapper()); } protected class ItemMapper implements RowMapper { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { Properties item = new Properties(); ResultSetMetaData rsmd = rs.getMetaData(); int len = rsmd.getColumnCount(); for (int i = 0; i < len; i = i + 1) { String colname = rsmd.getColumnName(i + 1); try { item.setProperty(colname, rs.getString(colname)); } catch (NullPointerException ex) { } } return item; } } public List queryForList(String sql, Object...objects) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); System.out.println(sql); List list = jdbcTemplate.queryForList(sql,objects); return list; } public int queryForInt(String sql,Object...objects) { System.out.println(sql); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); int result = jdbcTemplate.queryForInt(sql,objects); return result; } public int execute(String sql,Object...objects) { sql += ";"; String[] tempArray = sql.split("\\?"); String tempSql = tempArray[0]; for(int i=0;i<objects.length;i++){ tempSql += "‘"+objects[i]+"‘"+tempArray[i+1]; } System.out.println(tempSql); if( SecurityContextHolder.getContext().getAuthentication()!=null){ UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); Logger.logByDate("/data/log/sql/", "operation_sql", userDetails.getUsername()+"\t"+tempSql); } JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return jdbcTemplate.update(sql,objects); } /** * 分页查询 * @param sql * @param currentPage * @param numPerPage * @param objects * @return */ public PageInfo queryForPage(String sql, int currentPage, int numPerPage,Object...objects) { PageInfo pageinfo = new PageInfo(); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // String countsql = sql.replace(new String("*"), new String("COUNT(*)")); String countsql = "select COUNT(*) from (" + sql + ") as z"; if(sql.startsWith("SELECT *")){ if(sql.indexOf("WHERE")==-1 && sql.indexOf("where")==-1){ countsql = sql.replaceFirst("SELECT \\*", "SELECT COUNT(\\*)"); } } System.out.println(countsql); int count = jdbcTemplate.queryForInt(countsql,objects); pageinfo.setTotalCount(count); sql = sql + " Limit " + (currentPage - 1) * numPerPage + "," + numPerPage; //System.out.println(sql); List list = jdbcTemplate.queryForList(sql,objects); pageinfo.setCurrentPage(currentPage); pageinfo.setNumPerPage(numPerPage); pageinfo.setResult(list); return pageinfo; } /** * 查询单条记录 * @param sql * @param objects * @return */ public Map queryForOne(String sql,Object...objects) { Map map = new HashMap(); sql +=" limit 1"; JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); System.out.println(sql); List<Map<String,Object>> list = jdbcTemplate.queryForList(sql,objects); if(list.size()!=0){ return list.get(0); }else{ return map; } } /** * 插入Map 数据,key对应字段名,value对应字段值 * @param map * @param tableName * @param replace * @return */ public int insertMap(Map<String,String> map,String tableName,boolean replace){ int r = -1; int size = map.size(); String params[] = new String[size]; int index = 0; String insertkeySql = ""; String insertValueSql = ""; String comma = ""; Iterator<Entry<String, String>> it = map.entrySet().iterator(); while (it.hasNext()) { Entry<String, String> entry = (Entry<String, String>) it.next(); String k = entry.getKey(); String v = entry.getValue(); insertkeySql += comma + "`" + k + "`"; insertValueSql += comma + " ? "; comma = ", "; params[index] = v; index++; } String method = replace ? "REPLACE" : "INSERT"; String sql = method + " INTO " + tableName + " (" + insertkeySql + " ) VALUES ( " + insertValueSql + " )"; try { r = this.execUp(sql, params); } catch (Exception e) { e.printStackTrace(); } return r; } /** * 更新数据表 * @param setal 更新数据Map * @param whereal 条件Map * @param tablename 表名 * @return */ public int updateTable(Map<String, String> setal, Map<String, String> whereal, String tablename) { int r = -1; int size = setal.size() + whereal.size(); String params[] = new String[size]; int kid = 0; String setsql = ""; String comma = ""; Iterator<Entry<String, String>> it = setal.entrySet().iterator(); while (it.hasNext()) { Entry<String, String> entry = (Entry<String, String>) it.next(); String k = entry.getKey(); String v = entry.getValue(); setsql += comma + "`" + k + "`" + " = ? "; comma = ", "; params[kid] = v; kid++; } String where = ""; comma = ""; it = whereal.entrySet().iterator(); while (it.hasNext()) { if (where.equals("")) { where = " WHERE "; } Entry<String, String> entry = (Entry<String, String>) it.next(); String k = entry.getKey(); String v = entry.getValue(); String[] kw = k.split("[\\s,]"); if (kw.length == 2) { where += comma + " `" + kw[0] + "`" + " " + kw[1] + " ? "; } else if (kw.length == 3) { where += kw[0] + " `" + kw[1] + "`" + " " + kw[2] + " ? "; } else { where += comma + " `" + kw[0] + "`" + " = ? "; } comma = " AND "; params[kid] = v; kid++; } String sql = "UPDATE " + tablename + " SET " + setsql + where; // System.out.println( sql ); try { r = this.execUp(sql, params); } catch (Exception e) { e.printStackTrace(); } return r; } /** * 查询表 * @param columnNameSet * @param whereMap * @param orderBy * @param page * @param pageCount * @param tableName * @param onlyOne * @return */ public List<Properties> selectTable(Set<String> columnNameSet, Map<String, String> whereMap, String orderBy, int page, int pageCount, String tableName, boolean onlyOne) { int size = 0; String params[] = null; if (whereMap != null && whereMap.size() > 0) { size = whereMap.size(); params = new String[size]; } int kid = 0; String keysql = ""; String comma = ""; if (columnNameSet != null && columnNameSet.size() != 0) { for (String s : columnNameSet) { if (s.indexOf("(") != -1) { keysql += comma + "" + s + ""; } else { keysql += comma + "`" + s + "`"; } comma = " , "; } } else { keysql = " * "; } String where = ""; comma = ""; if (whereMap != null && whereMap.size() > 0) { Iterator<Entry<String, String>> it = whereMap.entrySet().iterator(); while (it.hasNext()) { if (where.equals("")) { where = " WHERE "; } Entry<String, String> entry = (Entry<String, String>) it.next(); String k = entry.getKey(); String v = entry.getValue(); String[] kw = k.split("[\\s,]"); if (kw.length == 2) { where += comma + " `" + kw[0] + "`" + " " + kw[1] + " ? "; } else if (kw.length == 3) { where += kw[0] + " `" + kw[1] + "`" + " " + kw[2] + " ? "; } else { where += comma + " `" + kw[0] + "`" + " = ? "; } comma = " AND "; params[kid] = v; kid++; } } String order = ""; if (orderBy.equals("") == false) { order = " ORDER BY " + orderBy; } String limit = ""; if (page > 0) { if (pageCount <= 0) { pageCount = 20; } int pageOffet = (page - 1) * pageCount; limit = " LIMIT " + pageOffet + "," + pageCount; } if (onlyOne == true) { limit = " LIMIT 1 "; } String sql = "SELECT " + keysql + " FROM " + tableName + where + order + limit; System.out.println(sql); List<Properties> l = null; try { l = this.execSql(sql, params); } catch (Exception e) { e.printStackTrace(); } return l; } public Properties getItem(Map<String, String> whereMap, String tableName) { Properties pp = null; try { List<Properties> l = selectTable(null, whereMap, "", -1, 0, tableName,true); if (l != null && l.size() > 0) { pp = l.get(0); } } catch (Exception ex) { ex.printStackTrace(); } return pp; } public Properties getItemById(String id, String tableName) { String sql = "SELECT * FROM " + tableName+ " WHERE `id` = ? Limit 1"; List<Properties> l = null; Properties pp = null; try { l = this.execSql(sql, new String[] { id }); if (l != null && l.size() > 0) { pp = l.get(0); } } catch (Exception ex) { ex.printStackTrace(); } return pp; } public Map getItemById(long userId, String tableName) { // TODO Auto-generated method stub String sql = "SELECT * FROM " + tableName+ " WHERE `id` = ? Limit 1"; List<Properties> l = null; Properties pp = null; try { l = this.execSql(sql, new String[] { String.valueOf(userId) }); if (l != null && l.size() > 0) { pp = l.get(0); } } catch (Exception ex) { ex.printStackTrace(); } return pp; } }
决策管理器AccessDecisionManager,判断用户的角色是否拥有操作的权限
package com.xj.security; import java.util.Collection; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; //决策管理器 public class MyAccessDecisionManager implements AccessDecisionManager{ //auth用户具有的权限,attributes访问该资源所需的角色权限 @Override public void decide(Authentication auth, Object object,Collection<ConfigAttribute> attributes) { for(ConfigAttribute ca:attributes){ //访问资源需要的权限 String needRole = ((SecurityConfig)ca).getAttribute(); for(GrantedAuthority ga:auth.getAuthorities()){ //用户拥有的权限 String role = ga.getAuthority(); if(role.equals(needRole)){ return; } } } } @Override public boolean supports(ConfigAttribute arg0) { return true; } @Override public boolean supports(Class<?> arg0) { return true; } }
基本配置就这样子
controller
package com.xj.action; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.xj.dao.CommonDao; @Controller public class HelloController { @Autowired private CommonDao commonDao; @RequestMapping(value="/hello/justtest") public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception { return new ModelAndView("/test"); } @RequestMapping(value="/login") public ModelAndView login(HttpServletRequest request,HttpServletResponse response) throws Exception { return new ModelAndView("/login"); } @RequestMapping(value="/main") public ModelAndView loginSuccess(HttpServletRequest request,HttpServletResponse response) throws Exception { return new ModelAndView("/main"); } }
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <font color="red"> <c:choose> <c:when test="${SPRING_SECURITY_LAST_EXCEPTION.message == ‘Bad credentials‘}">用户名或密码错误 </c:when> <c:otherwise> <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"></c:out> </c:otherwise> </c:choose> </font> <br/> <form action="j_spring_security_check" method="post"> 用户名:<input type="text" name="j_username" /><br/> 密码:<input type="password" name="j_password"/> <br/> <input id="_spring_security_remember_me" name="_spring_security_remember_me" type="checkbox" value="true"/>记住我<br/> <input type="submit" value="登陆"/> </form> </body> </html>
main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <base href="<%=basePath%>"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> this is main page <a href="hello/justtest">继续前进</a> <a href="j_spring_security_logout">退出</a> </body> </html>
大概就这样子了。
整个项目网盘地址为:http://yun.baidu.com/share/link?shareid=2188454084&uk=2836507213
本文出自 “bulajunjun” 博客,请务必保留此出处http://5148737.blog.51cto.com/5138737/1615882
原文地址:http://5148737.blog.51cto.com/5138737/1615882