spring security

spring security 咱們主要是圍繞非業務合同項目對spring security的使用進行展開。 咱們總體瞭解一下這些配置web

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	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:beans="http://www.springframework.org/schema/beans" 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.xsd
		http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
//上面配置的是命名空間

        //線面配置的是路徑及路徑的訪問權限。pattern爲路徑,secutity爲權限,權限爲none爲都可訪問
	<http pattern="/resources/**" security="none" />//這一條是訪問資源路徑,由於每一個人都須要獲取本身的資源路徑以後才能夠進行權限控制,因此這裏的權限爲none,同理下面的登陸和獲取驗證碼的路徑
	<http pattern="/login" security="none" />
	<http pattern="/" security="none" />
	
	<http pattern="/captchaImage/**" security="none" />
	 


	<http access-decision-manager-ref="accessDecisionManager"
		entry-point-ref="authenticationEntryPoint" authentication-manager-ref="authenticationManager">
		<intercept-url pattern="/**" access="RBAC" />
		<logout logout-url="/logout" success-handler-ref="simpleUrlLogoutSuccessHandler" />
		<custom-filter ref="customUsernamePasswordAuthenticationFilter"  position="FORM_LOGIN_FILTER" />
		<custom-filter ref="concurrentSessionFilter" position="CONCURRENT_SESSION_FILTER" />
		<custom-filter ref="ajaxSessionTimeoutFilter" before="SESSION_MANAGEMENT_FILTER" />
		<!-- <custom-filter ref="systemPathFilter" before="FORM_LOGIN_FILTER" />
		<custom-filter ref="addUserToSessionFilter" after="REMEMBER_ME_FILTER" />
		<custom-filter ref="topMenuBackgroundFilter" before="LAST" /> -->
		<custom-filter ref="addUserToSessionFilter" after="REMEMBER_ME_FILTER" />
		<csrf disabled="true" />

		<!-- 設置x-frame-options,不然ajaxfileupload組件提示x-frame-options錯誤 -->
		<headers>
			<frame-options policy="
			SAMEORIGIN" />
		</headers>

		<!-- 容許匿名用戶 -->
		<!-- <anonymous /> -->

		<!-- 記住密碼,默認記住2周 -->
		<!-- <remember-me services-ref="rememberMeServices" key="contract" authentication-success-handler-ref="rememberMeAuthenticationSuccessHandler"/> -->

		<session-management
			session-authentication-strategy-ref="compositeSessionAuthenticationStrategy"
			invalid-session-url="/">
		</session-management>

		<access-denied-handler ref="accessDeniedHandler" />
	</http>


	<!-- <beans:bean id="rememberMeServices"
		class="com.incoshare.base.security.CustomTokenBasedRememberMeServices">
		<beans:constructor-arg value="contract"></beans:constructor-arg>
		<beans:constructor-arg ref="jdbcUserService"></beans:constructor-arg>
	</beans:bean> -->

	<!-- <beans:bean id="sessionRegistry"
		class="com.incoshare.base.security.CustomSpringSessionBackedSessionRegistry">
		<beans:constructor-arg ref="sessionRepository"></beans:constructor-arg>
	</beans:bean> -->
	<beans:bean id="sessionRegistry"
        class="org.springframework.security.core.session.SessionRegistryImpl" />

	<beans:bean id="compositeSessionAuthenticationStrategy"
		class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
		<beans:constructor-arg>
			<beans:list>
				<beans:ref bean="concurrentSessionControlAuthenticationStrategy" />
				<beans:ref bean="sessionFixationProtectionStrategy" />
				<beans:ref bean="registerSessionAuthenticationStrategy" />
			</beans:list>
		</beans:constructor-arg>
	</beans:bean>

	<beans:bean id="concurrentSessionControlAuthenticationStrategy"
		class="com.contract.base.security.CustomConcurrentSessionControlAuthenticationStrategy">
		<beans:constructor-arg ref="sessionRegistry"></beans:constructor-arg>
	</beans:bean>

	<beans:bean id="registerSessionAuthenticationStrategy"
		class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
		<beans:constructor-arg ref="sessionRegistry"></beans:constructor-arg>
	</beans:bean>

	<beans:bean id="sessionFixationProtectionStrategy"
		class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
	</beans:bean>

	<beans:bean id="concurrentSessionFilter"
		class="org.springframework.security.web.session.ConcurrentSessionFilter">
		<beans:constructor-arg ref="sessionRegistry"></beans:constructor-arg>
		<beans:constructor-arg value="/"></beans:constructor-arg>
	</beans:bean>
        
        <--AuthenticationEntryPoint是spring-security的一個起點,在這個起點,收集用戶的信息,通常把這個入口設置在登陸頁面,LoginUrlAuthenticationEntryPoint爲其實現類-->
	<beans:bean id="authenticationEntryPoint"
		class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
		p:useForward="true">
		<beans:constructor-arg value="/login"></beans:constructor-arg>
	</beans:bean>

	<beans:bean id="ajaxSessionTimeoutFilter"
		class="com.contract.base.security.AjaxSessionTimeoutFilter">
	</beans:bean>

	<!-- <beans:bean id="topMenuBackgroundFilter"
		class="com.incoshare.base.security.TopMenuBackgroundFilter">
	</beans:bean> -->


	<beans:bean id="accessDeniedHandler"
		class="com.contract.base.security.CustomAccessDeniedHandlerImpl"
		p:errorPage="/denyAccess" />

	<beans:bean id="simpleUrlLogoutSuccessHandler"
		class="com.contract.base.security.CustomSimpleUrlLogoutSuccessHandler" 
		p:targetUrlParameter="logoutToUrl" />
		<!-- p:redisTemplate-ref="redisTemplate" -->

//這裏是一個可否進入的決定管理者,他是經過一個投票中心決定的
	<beans:bean id="accessDecisionManager"
		class="org.springframework.security.access.vote.AffirmativeBased">
		<beans:constructor-arg>
			<beans:list>
				<beans:ref bean="rbacVoter" />
			</beans:list>
		</beans:constructor-arg>
	</beans:bean>
        <--投票機制的實現,實際上是對路徑的控制,哪路請求能夠訪問,哪些不能-->
	<beans:bean id="rbacVoter" class="com.contract.base.security.RbacVoter" />


	<beans:bean id="authenticationFailureHandler"
		class="com.contract.base.security.CustomSimpleUrlAuthenticationFailureHandler"
		p:defaultFailureUrl="/login" p:useForward="true" />

	<beans:bean id="authenticationSuccessHandler"
		class="com.contract.base.security.CustomAuthenticationSuccessHandler"
		p:alwaysUseDefaultTargetUrl="true" />

	<!-- <beans:bean id="rememberMeAuthenticationSuccessHandler"
		class="com.incoshare.base.security.CustomRememberMeAuthenticationSuccessHandler"
		p:alwaysUseDefaultTargetUrl="true" />
 -->

	<beans:bean id="passwordEncoder"
		class="com.contract.base.security.CustomMessageDigestPasswordEncoder">
		<beans:constructor-arg value="md5"></beans:constructor-arg> 
		<beans:constructor-arg value="true"></beans:constructor-arg>
	</beans:bean>

	<beans:bean id="customWebAuthenticationDetailsSource"
		class="com.contract.base.security.CustomWebAuthenticationDetailsSource">
	</beans:bean>

	<beans:bean id="customUsernamePasswordAuthenticationFilter"
		class="com.contract.base.security.CustomUsernamePasswordAuthenticationFilter"
		p:authenticationManager-ref="authenticationManager"
		p:filterProcessesUrl="/doLogin" p:sessionAuthenticationStrategy-ref="compositeSessionAuthenticationStrategy"
		p:authenticationSuccessHandler-ref="authenticationSuccessHandler"
		p:authenticationFailureHandler-ref="authenticationFailureHandler"    
		p:authenticationDetailsSource-ref="customWebAuthenticationDetailsSource">
		<!-- p:rememberMeServices-ref="rememberMeServices" -->
	</beans:bean>

	<beans:bean id="authenticationProvider"
		class="com.contract.base.security.CustomDaoAuthenticationProvider"
		p:userDetailsService-ref="jdbcUserService"
		 p:passwordEncoder-ref="passwordEncoder">
		
	</beans:bean>

	<!-- <beans:bean id="ipAuthenticationProvider"
		class="com.incoshare.base.security.CustomIpDaoAuthenticationProvider"
		p:userDetailsService-ref="ipuserJdbcDaoImpl">
	</beans:bean>

	<beans:bean id="ipuserJdbcDaoImpl"
		class="com.incoshare.base.security.IpuserJdbcDaoImpl"
		p:dataSource-ref="dataSource">
	</beans:bean> -->

	<authentication-manager alias="authenticationManager"
		id="authenticationManager" erase-credentials="false">
		<authentication-provider ref="authenticationProvider">
		</authentication-provider>
		<!-- <authentication-provider ref="ipAuthenticationProvider">
		</authentication-provider> -->
	</authentication-manager>

	<beans:bean id="jdbcUserService"
		class="com.contract.base.security.CustomJdbcDaoImpl"
		p:dataSource-ref="dataSource"
		p:usersByUsernameQuery="SELECT employee_account,employee_password,1 FROM contract_employee WHERE employee_account=?"
		p:authoritiesByUsernameQuery="SELECT ce.employee_account,cer.role_id FROM contract_employee ce,contract_employee_role cer WHERE ce.employee_id=cer.employee_id AND ce.employee_account=?">
	</beans:bean>


	<beans:bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<beans:property name="basename"
			value="classpath:messages/security/messages" />
	</beans:bean>
	<!-- <beans:bean id="localeResolver"
		class="org.springframework.web.servlet.i18n.SessionLocaleResolver" /> -->

</beans:beans>

rbacVoter投票類ajax

//首先這個類要實現AccessDecisionVoter 接口,也是spring-security的默認接口
public class RbacVoter implements AccessDecisionVoter {
        
        //這裏注入的是具體某個項目查詢權限的業務層實現類/接口
	@Autowired
	private ContractEmployeeService contractEmployeeService;

	// 每一個登陸用戶都能訪問的url,這些url定義爲一個靜態數組
	public static String[] shouldPassUrls = {
			"/",//注意這裏是/不是/*
			"/index",//訪問默認頁面
			"/image/**",//訪問圖片
			
	};
        
//查看一個請求是否爲異步請求,
	private boolean isAjax(HttpServletRequest request) {
		return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest"
				.equals(request.getHeader("X-Requested-With").toString()));
	}
//實現的重寫方法,該方法返回0則沒有權限訪問,返回1則能夠訪問
//這個類的vote方法,基本上是每次強求後臺,都須要進入這個方法,這有在spring-security.xml中配置security爲none的pattern纔不會進入該方法
	public int vote(Authentication authentication, Object object,
			Collection attributes) {
                //這裏是一個過濾器序列,並獲取當前的請求路徑
		FilterInvocation fi = (FilterInvocation) object;
		String url = fi.getRequestUrl();
                //這裏是經過spring的身份認證類,獲取當前登陸用戶的帳號
		String name = authentication.getName();

		// 這裏是一些相似業務上比較特殊的路徑,能夠不用權限和登陸,直接就經過,
		if (url.startsWith("/a/init") || url.startsWith("/a/upload") || url.startsWith("/a/download")) {
			return 1;
		}

                //下面的邏輯比較常規就是經過登陸員工,查詢該員工擁有的權限
		ContractEmployee contractEmployee = this.contractEmployeeService.selectByAccount(name);
                //若是目前登陸,則繼續執行邏輯。不然直接回復0(即拒絕)
		if (contractEmployee != null) {

			// 對於一些全部用戶都應該能訪問的url,不作限制,上面靜態數組定義的路徑
			for (String turl : this.shouldPassUrls) {
                                //這是一個url匹配器,能夠識別url通配符,噹噹前請求路徑和靜態中的路徑匹配時,返回1,這裏要注意,靜態類中的路徑,通常都是帶有通配符的,而,上面業務是上直接放行的路徑,只能是具體的某個請求路徑。
				AntPathRequestMatcher matcher = new AntPathRequestMatcher(turl);
				if (matcher.matches(fi.getHttpRequest())) {
					return 1;
				}
			}
                        //查找該員工所擁有的權限,遍歷
			for (ContractResource p : this.contractEmployeeService.selectResources(contractEmployee.getEmployeeId())) {
				if (p.getResourceUrl() == null) {
					continue;
				}
				String[] urls = p.getResourceUrl().split(",");
				for (String permissionUrl : urls) {
					if (StringUtils.isNotBlank(permissionUrl)) {
                                                //現有路徑一樣匹配請求路徑,匹配則返回1
						AntPathRequestMatcher matcher = new AntPathRequestMatcher(
								permissionUrl);
                            
						if (matcher.matches(fi.getHttpRequest())) {
							return 1;
						}
					}
				}

			}

		}

		return 0;
	}

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

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

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