说到权限系统,几乎每个系统都要用到,只要涉及到人操作和管理的的系统。而权限系统的核心那就是:授权和认证。
大道至简,根据这个核心所有的第三方还是适合自己的权限系统都围绕此进行。
Spring Security 也是如此,在系统中怎样接入Spring Security呢?主要有以下几步:
1、配置文件
<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.spr ingframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http>
<intercept-url pattern="/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-page="/login.htm" login-processing-url="/login_process.htm"
authentication-failure-url="/login.htm?error=true" default-target-url="/index.htm"
password-parameter="password" username-parameter="username" />
<http-basic />
<logout logout-success-url="/login.htm" logout-url="/logout.htm"/>
<remember-me token-validity-seconds="604800" /> <!-- 1 week -->
<custom-filter ref="resourceSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="securityManager">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="securityManager" class="com.apache.platform.service.authorization.SecurityManagerSupport"></beans:bean>
<beans:bean id="resourceSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<!-- 认证管理 -->
<beans:property name="authenticationManager" ref="authenticationManager"/>
<!-- 访问决策 -->
<beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
<!-- 资源定义 -->
<beans:property name="securityMetadataSource" ref="secureResourceFilterInvocationDefinitionSource" />
</beans:bean>
<!-- 访问决策器 -->
<beans:bean id="accessDecisionManager"
class="com.apache.platform.service.authorization.AccessDecisionManager">
</beans:bean>
<beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.apache.platform.service.authorization.SecureResourceFilterInvocationDefinitionSource" />
</beans:beans>
整个权限系统的接入围绕这个配置文件展开。
1》 认证管理
主要提供用户登录访问认证操作
2》 访问决策
对资源访问定义规则和策略
3》 资源定义
根据认证用户加载访问资源
SecurityManagerSupport.java
/**
*
*/
package com.apache.platform.service.authorization;
import java.util.ArrayList;
import java.util.Collection;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.context.ServletContextAware;
import com.apache.platform.common.CommConstant;
import com.apache.platform.service.IUserManager;
/**
* @author tangss
* @2013年9月28日 @上午9:19:25
*/
public class SecurityManagerSupport implements UserDetailsService, ServletContextAware {
@Autowired
private IUserManager userManager;
ServletContext servletContext;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails user = null;
if (StringUtils.isNotEmpty(username) && username.equals("test")) {
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("admin_role"));
user = new UserInfo(username, "e10adc3949ba59abbe56e057f20f883e", true, true, true, true, authorities);
} else {
user = userManager.getUserByUserName(username);
}
this.servletContext.setAttribute(CommConstant.USER_INFO, user);
return user;
}
/*
* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
}
AccessDecisionManager.java
package com.apache.platform.service.authorization;
import java.util.Collection;
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 AccessDecisionManager implements org.springframework.security.access.AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException,
InsufficientAuthenticationException {
if (configAttributes == null) {
return;
}
for (ConfigAttribute ca : configAttributes) {
String needRole = ((SecurityConfig) ca).getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needRole.equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("没有权限");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
SecureResourceFilterInvocationDefinitionSource.java
/**
*
*/
package com.apache.platform.service.authorization;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.ServletContext;
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 org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;
import org.springframework.web.context.ServletContextAware;
import com.apache.platform.common.CommConstant;
/**
* @author tangss
* @2013年9月28日 @上午9:44:38
*/
public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationSecurityMetadataSource, ServletContextAware {
private Map<String, String> linkMap;
private Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
// 获得请求资源所需的权限
@Override
public Collection<ConfigAttribute> getAttributes(Object filter) throws IllegalArgumentException {
if (linkMap == null || linkMap.isEmpty()) {
return null;
}
RequestMatcher matcher = null;
Set<Entry<String, String>> linkSet = linkMap.entrySet();
for (Entry<String, String> entry : linkSet) {
String url = entry.getKey();
matcher = new AntPathRequestMatcher(url);
if (matcher.matches(((FilterInvocation) filter).getRequest())) {
Collection<ConfigAttribute> configAttributes = resourceMap.get(url);
if (configAttributes != null) {
return configAttributes;
}
// 解析 role
String value = entry.getValue(); // split by comma
String values[] = value.split(",");
configAttributes = new ArrayList<ConfigAttribute>();
for (String attribute : values) {
ConfigAttribute configAttribute = new SecurityConfig(attribute);
configAttributes.add(configAttribute);
}
resourceMap.put(url, configAttributes);
return configAttributes;
}
}
return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@SuppressWarnings("unchecked")
@Override
public void setServletContext(ServletContext servletContext) {
linkMap = (Map<String, String>) servletContext.getAttribute(CommConstant.LINK_MAP);
}
}
2、登录页面
#set($layout = "/layout/blankLayout.vm")
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>登录</title>
<script type="text/javascript" src="$!{scriptsPath}scripts/common/jquery-1.10.2.js"></script>
<link rel="stylesheet" type="text/css" href="$!{stylesPath}styles/login.css" />
</head>
<body>
<form method="post" action="login_process.htm">
<div class="login">
<p>
用户名:<input type="text" name="username" />
<p>
密 码:<input type="password" name="password" />
</p>
</p>
<p>
<input type="checkbox" name="_spring_security_remember_me" /> 记住我
</p>
<p>
<input type="submit" value="登 录" class="btn" />
</p>
</div>
</form>
</body>
</html>
3 、web.mxl 配置
<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>*.htm</url-pattern>
</filter-mapping>
4、maven pom.xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.4.RELEASE</version>
</dependency>