SpringSecurity數據庫中存儲用戶、角色、資源

這幾天項目中用到了SpringSecurity作登錄安全。因此在這寫一下也許能夠幫助一下其餘人,本身也熟悉一下html

SpringSecurity配置文件以下:java

<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">
	
	<!-- 這個元素用來在你的應用程序中啓用基於安全的註解 
    <global-method-security  pre-post-annotations="enabled" access-decision-manager-ref="myAccessDecisionManager"/>
    -->
	<http pattern="/index.html" security="none" />	
	
	<http auto-config="true">		
		<logout logout-success-url="/app/login" />
		<form-login login-page="/app/login" default-target-url="/app/admin"
			authentication-failure-url="/app/loginfailed" />
			
		<!-- "記住我"功能,採用持久化策略(將用戶的登陸信息存放在數據庫表中) -->
		<!-- <remember-me data-source-ref="dataSource" /> -->
		
		<!-- 增長一個自定義的filter,放在FILTER_SECURITY_INTERCEPTOR以前,
		實現用戶、角色、權限、資源的數據庫管理-->
		<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> 
		
	</http>
	
	<!-- 實現了UserDetailsService的Bean -->	
	<authentication-manager alias="myAuthenticationManager">
		<authentication-provider user-service-ref="myUserDetailService">
		     <password-encoder hash="plaintext">
             </password-encoder>		   
			<!-- <password-encoder ref="passwordEncoder">
			    <salt-source user-property="username" />
			</password-encoder> -->			 
		</authentication-provider>
	</authentication-manager>

	<!-- 
	             一個自定義的filter,必須包含
	     authenticationManager, 
	     accessDecisionManager,
	     securityMetadataSource 三個屬性。
	 -->
	<beans:bean id="myFilter"
		class="com.yihaomen.common.intercept.MyFilterSecurityInterceptor">
		<!-- 用戶擁有的權限 -->
		<beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property>
		<!-- 用戶是否擁有所請求資源的權限 -->
		<beans:property name="accessDecisionManager" ref="myAccessDecisionManager"></beans:property>
		<!-- 資源與權限對應關係 -->
		<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"></beans:property>
	</beans:bean>
	
</beans:beans>

 全部的實現邏輯便在這個FilterInterceptor之中,主要的實現的是這個Interceptor中的三個屬性,而實現的這三個類:web

Interceptor:spring

package com.yihaomen.common.intercept;

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.beans.factory.annotation.Autowired;
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 MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

	// 與spring-security.xml裏的myFilter的屬性securityMetadataSource對應,
	// 其餘的兩個組件,已經在AbstractSecurityInterceptor定義
	@Autowired
	private FilterInvocationSecurityMetadataSource securityMetadataSource;

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		FilterInvocation fi = new FilterInvocation(request, response, chain);
		invoke(fi);

	}

	public Class<? extends Object> getSecureObjectClass() {
		return FilterInvocation.class;
	}

	public void invoke(FilterInvocation fi) throws IOException,
			ServletException {
		// object爲FilterInvocation對象
		// super.beforeInvocation(fi);源碼
		// 1.獲取請求資源的權限
		// 執行Collection<ConfigAttribute> attributes =
		// SecurityMetadataSource.getAttributes(object);
		// 2.是否擁有權限
		// this.accessDecisionManager.decide(authenticated, object, attributes);
		InterceptorStatusToken token = super.beforeInvocation(fi);

		try {
			fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
		} finally {
			super.afterInvocation(token, null);
		}

	}

	@Override
	public SecurityMetadataSource obtainSecurityMetadataSource() {
		return this.securityMetadataSource;
	}

	public void setSecurityMetadataSource(
			FilterInvocationSecurityMetadataSource securityMetadataSource) {
		this.securityMetadataSource = securityMetadataSource;
	}

	public void destroy() {

	}

	public void init(FilterConfig filterconfig) throws ServletException {

	}

}

 

package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
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.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.yihaomen.common.dao.ResourcesDao;
import com.yihaomen.common.domain.SysResource;

public class MyInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {

	@Autowired
	private ResourcesDao resourcesDao;

	// resourceMap及爲key-url,value-Collection<ConfigAttribute>,資源權限對應Map
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public MyInvocationSecurityMetadataSourceService(ResourcesDao resourcesDao) {
		this.resourcesDao = resourcesDao;
		System.out.println("加載MyInvocationSecurityMetadataSourceService..."
				+ resourcesDao);
		loadResourceDefine();
	}

	// 加載全部資源與權限的關係
	private void loadResourceDefine() {
		if (resourceMap == null) {
			resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
			List<SysResource> resources = resourcesDao.findAll();
			// 加載資源對應的權限
			for (SysResource resource : resources) {
				Collection<ConfigAttribute> auths = resourcesDao
						.loadRoleByResource(resource.getResource());
				System.out.println("權限=" + auths);
				resourceMap.put(resource.getResource(), auths);
			}
		}
	}

	//由資源路徑得到權限
	//object爲請求的資源路徑
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		// object是一個URL,被用戶請求的url
		String requestUrl = ((FilterInvocation) object).getRequestUrl();
		System.out.println("requestUrl is " + requestUrl);
		
		int firstQuestionMarkIndex = requestUrl.indexOf("?");
		//若是請求的資源路徑有?後面的參數,則將?後面的切掉,以避免拒絕訪問
		if (firstQuestionMarkIndex != -1) {
			requestUrl = requestUrl.substring(0, firstQuestionMarkIndex);
		}

		if (resourceMap == null) {
			loadResourceDefine();
		}
		//
		Iterator<String> ite = resourceMap.keySet().iterator();
		//根據資源路徑得到其所需的權限
		while (ite.hasNext()) {
			String resURL = ite.next();

			if (resURL.equals(requestUrl)) {
				return resourceMap.get(resURL);
			}
		}
		return null;
	}

	public boolean supports(Class<?> arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		// TODO Auto-generated method stub
		return null;
	}

}

 

package com.yihaomen.comm.service;

import java.sql.SQLException;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.yihaomen.common.dao.UserInfoDao;
import com.yihaomen.common.domain.SysUser;
/**
 * 根據用戶名得到其所擁有的權限,返回該用戶的狀態信息。並將其所擁有的權限放入GrantedAuthority中
 * @author Administrator
 *
 */
public class MyUserDetailService implements UserDetailsService {
	@Autowired
	private UserInfoDao userInfoDao;
	
	@Autowired
	private UserCache userCache;

	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		System.out.println("username is :" + username);

		SysUser user = null;
		try {
			user = this.userInfoDao.findByName(username);
			System.out.println(user);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 得到用戶權限
		Collection<GrantedAuthority> auths = userInfoDao
				.loadUserAuthorityByName(username);
		

		boolean enables = true;
		// 帳戶過時否
		boolean accountNonExpired = true;
		// 證書過時否
		boolean credentialsNonExpired = true;
		// 帳戶鎖定否
		boolean accountNonLocked = true;
		// 封裝成spring security的user
		User userdetail = new User(username, user.getPassword(), enables,
				accountNonExpired, credentialsNonExpired, accountNonLocked,
				auths);
		for (GrantedAuthority s : auths) {
			s.getAuthority();
		}
		System.out.println(auths);
		return userdetail;

	}

	public UserInfoDao getUserInfoDao() {
		return userInfoDao;
	}

	public void setUserInfoDao(UserInfoDao userInfoDao) {
		this.userInfoDao = userInfoDao;
	}

	//設置用戶緩存功能。
	public UserCache getUserCache() {
		return userCache;
	}

	public void setUserCache(UserCache userCache) {
		this.userCache = userCache;
	}
	

}

 

package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class MyAccessDecisionManager implements AccessDecisionManager {

	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {

		if (configAttributes == null) {
			return;
		}

		//所請求的資源擁有的權限(一個資源對多個權限)
		Iterator<ConfigAttribute> ite = configAttributes.iterator();

		while (ite.hasNext()) {

			ConfigAttribute ca = ite.next();
			//訪問所請求資源所須要的權限 
			String needRole = ((SecurityConfig) ca).getAttribute();
			System.out.println("needRole is " + needRole); 
			// ga 爲用戶所被賦予的權限。 needRole 爲訪問相應的資源應該具備的權限。
			for (GrantedAuthority ga : authentication.getAuthorities()) {

				if (needRole.trim().equals(ga.getAuthority().trim())) {

					return;
				}

			}

		}
		//沒有權限
		throw new AccessDeniedException("沒有權限訪問!");

	}

	public boolean supports(ConfigAttribute arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	public boolean supports(Class<?> arg0) {
		// TODO Auto-generated method stub
		return true;
	}

}
相關文章
相關標籤/搜索