Spring Security 认证 根据数据库自动授权
<?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-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> <!-- org.springframework.security.providers.dao.cache.EhCacheBasedUserCache --> <beans:bean id="userCache" ref="userEhCache" /> </beans:bean> <beans:bean id="cacheManager" /> <beans:bean id="userEhCache" ref="cacheManager" /> <beans:property name="cacheName" value="userCache" /> </beans:bean> <!-- jsp 资源保护 --> <http auto-config="true" access-denied-page="/common/403.jsp" session-fixation-protection="none"> <!-- intercept-url pattern="/admin.jsp" requires-channel="https"/ --> <!-- <intercept-url pattern="/" filters="none" />限制匿名登陆 --> <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/" /> <logout logout-success-url="/login.jsp" /> <port-mappings> <port-mapping http="8080" https="9443" /> </port-mappings> <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true" /> <!-- 匿名身份:Guest --> <anonymous username="Guest" /> </http> <!-- 用户 合法性认证 --> <authentication-provider> <password-encoder hash="md5" /> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT userinfo_name,userinfo_pwd,1 AS 'enabled' FROM up_userinfo WHERE userinfo_name = ? " authorities-by-username-query="SELECT up_userinfo.userinfo_name,('ROLE_'+LTRIM(str(up_role.role_id))) as 'role' FROM up_userrole inner join up_userinfo on up_userrole.userinfo_id=up_userinfo.userinfo_id inner join up_role on up_role.role_id=up_userrole.role_id WHERE up_userinfo.userinfo_name = ? " cache-ref="userCache" /> </authentication-provider> <beans:bean id="filterSecurityInterceptor" /> <beans:property name="objectDefinitionSource" ref="filterInvocationDefinitionSource" /> </beans:bean> <!-- 根据数据库中的内容自动为用户授权 --> <beans:bean id="filterInvocationDefinitionSource" ref="dataSource" /> <beans:property name="resourceQuery" value="select distinct _source.resource_link, ('ROLE_'+LTRIM(str(_role.role_id))) as ROLE ,_role.role_name from up_role _role JOIN up_privilege _pri ON _role.role_id=_pri.role_id JOIN up_resource _source ON _pri.resource_id=_source.resource_id WHERE _source.resource_link not like ''" /> </beans:bean> <!-- 数据源 --> <beans:bean id="dataSource" /> <beans:property name="url" value="jdbc:jtds:sqlserver://localhost:1433;DatabaseName=eBuilder_egov;useLOBs=false" /> <beans:property name="username" value="sa" /> <beans:property name="password" value="sa1" /> </beans:bean> <!-- logger debug listener --> <beans:bean id="loggerListener" /></beans:beans>
?需要些什么包呢:
?
?
?
?
?
?
Web.xml
?
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <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> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener><listener> <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class></listener> </web-app>
?
?
?
?
?
自定义的一个加载权限和角色对应的类
?
MySecureResourceFilter.java
?
?
package org.springframework.security.SecureFilter;import java.sql.ResultSet;import java.sql.SQLException;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import javax.sql.DataSource;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.FactoryBean;import org.springframework.jdbc.core.support.JdbcDaoSupport;import org.springframework.jdbc.object.MappingSqlQuery;import org.springframework.security.ConfigAttributeDefinition;import org.springframework.security.ConfigAttributeEditor;import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;import org.springframework.security.intercept.web.RequestKey;import org.springframework.security.util.AntUrlPathMatcher;import org.springframework.security.util.UrlMatcher;/** * SS(Spring Security) 根据Web.xml指定的xml配置文件(在其中配置好resourceQuery)自动授权 * @author 杨伦亮 * Dec 14, 2010 */public class MySecureResourceFilter extends JdbcDaoSupport implements FactoryBean { private String resourceQuery; private final Log log=LogFactory.getLog(MySecureResourceFilter.class); public boolean isSingleton() { return true; } public Class getObjectType() { return FilterInvocationDefinitionSource.class; } /** * 我扩展的功能: urlMatcher和requestMap创建DefaultFilterInvocationDefinitionSource。 */ public Object getObject() { return new DefaultFilterInvocationDefinitionSource(this.getUrlMatcher(), this .buildRequestMap()); } /** * 方法获得所有资源信息。<br>默认的情况是从XML配置文件中读取此信息即类似URL与ROLE_ADMIN信息。现在改为自定义地去查找数据库中的信息并与之对应 * @return Map */ protected Map<String, String> findResources() { //获得DataSource ResourceMapping resourceMapping = new ResourceMapping(getDataSource(), resourceQuery); Map<String, String> resourceMap = new LinkedHashMap<String, String>(); String url,role,value; //execute()方法获得所有资源信息。 Log log=LogFactory.getLog(MySecureResourceFilter.class); for(Resource resource : (List<Resource>) resourceMapping.execute()){ url = resource.getUrl(); role = resource.getRole(); if(resourceMap.containsKey(url)){ value = resourceMap.get(url); log.info(url+"\t授权:"+value+","+role+"\n"); resourceMap.put(url, value +"," +role); }else{ log.info(url+"\t授权:"+role+"\n"); resourceMap.put(url, role); } } return resourceMap; } /** * 使用获得的资源信息组装requestMap。 * @return LinkedHashMap */ protected LinkedHashMap<RequestKey, ConfigAttributeDefinition> buildRequestMap() { LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap = null; requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); Map<String, String> resourceMap = this.findResources(); for(Map.Entry<String, String> entry : resourceMap.entrySet()){ RequestKey key = new RequestKey(entry.getKey(), null); editor.setAsText(entry.getValue()); requestMap.put(key, (ConfigAttributeDefinition) editor.getValue()); } return requestMap; } protected UrlMatcher getUrlMatcher() { return new AntUrlPathMatcher(); } public void setResourceQuery(String resourceQuery) { log.info("setResourceQuery()\t"+resourceQuery); this.resourceQuery = resourceQuery; } /** * 资源属性<br>链接地址及角色名 * @author 杨伦亮 * Dec 15, 2010 */ private class Resource { private String url; private String role; public Resource(String url, String role) { this.url = url; this.role = role; } public String getUrl() { return url; } public String getRole() { return role; } } private class ResourceMapping extends MappingSqlQuery { protected ResourceMapping(DataSource dataSource, String resourceQuery) { super(dataSource, resourceQuery); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String url = rs.getString(1); String role = rs.getString(2); Resource resource = new Resource(url, role); return resource; } } }
?
?
?
?
下面来测试一下配置信息是否对
admin.jsp
?
<%@ page language="java" import="java.util.*,org.springframework.security.*,org.springframework.security.userdetails.*,org.springframework.security.context.*" pageEncoding="UTF-8"%><%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body > <h3> <a href="index.jsp">Home</a> | <a href="admin.jsp" target=_blank>试试访问受保护的jsp(403表示无权限访问)</a> | <a href="button_admin.jsp">只保护jsp中的按钮</a> | 当前用户 <a href="j_spring_security_logout">重新登陆</a> : <sec:authentication property="name"></sec:authentication>[${authentication.username }] <input type="button" value='<sec:authentication property="name" />' /> </h3> <p> 权限列表: </p> <% try{ //当前登陆对象 SecurityContext sec = SecurityContextHolder.getContext(); UserDetails userDetails = (UserDetails) sec.getAuthentication().getPrincipal(); out.print("["+userDetails.getUsername()+"]<br>"); //取得权限列表 GrantedAuthority[] authorities = userDetails.getAuthorities(); for(int size = authorities.length, i = 0; i <size; i++){ if(authorities[i] ==null) break; out.print("<br><font color=green>" +authorities[i] ==null ? "" : authorities[i].toString()+"</font>"); } }catch(Exception e){ out.print("<script>document.write('<font color=ffffff>Exception:!!!" +e.getMessage() +"</font>');</script>"); } %> <font color=ffffff> <sec:authentication property="authorities" /> </font> <br> <hr><h3>Session:</h3> <% Enumeration<String> s=session.getAttributeNames(); try{ //UserDetails userdetails=(UserDetails)session.getAttribute(); while(s.hasMoreElements()){ String key=s.nextElement(); out.println("<font color=red>"+key+"</font> <font color=green>"+session.getAttribute(key)+"</font><br>");//这里的s.nextElement()就对应了每一个键名 通过他取值就可以了 } }catch(java.util.NoSuchElementException e){ out.println("认证失败"+e.getMessage()); }%> </body></html>
?