spring-secrity
2017-01-22 17:04
344 查看
一部分是自己项目中使用到的,一些是看网上大神写的,自己以前虽然用但是没有人家写的注释的那么详细。
所以都贴出来。以后如果发现又新的东西再继续添加。
这个是 spring-secrity 配置文件。 自己项目的配置
这个是大神的配置
然后是 <beans:bean id="mySecurityFilter" class="com.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>
下面是红色文件的内容。 这个基本使用 内容都是一样。大神的注释比较代码。这个文件一般不用修改,直接使用就好。因为大神的内容所以 文件名不一样
<beans:bean id="mySecurityFilter" class="com.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>
<beans:bean id="myAccessDecisionManager"
class="com.base.security.XaAccessDecisionManagerService" />
//参数authentication是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息
//参数object是url
//参数configAttributes所需的权限
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) {
return;
}
Iterator<ConfigAttribute> iterator = configAttributes.iterator();
while (iterator.hasNext()) {
ConfigAttribute configAttribute = iterator.next();
String needPermission = configAttribute.getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needPermission.equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("没有权限访问");
}
public boolean supports(ConfigAttribute attribute) {
// TODO Auto-generated method stub
return true;
}
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
}
<beans:bean id="mySecurityFilter" class="com.xa3ti.qingbaosouji.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"
/>
</beans:bean>
package com.base.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.base.constant.XaConstant;
import com.base.entity.XaCmsRole;
import com.base.repository.XaCmsResourceRepository;
import com.base.repository.XaCmsRoleRepository;
import com.base.util.XaUtil;
@Service("MsSecurityMetadataSourceService")
@Transactional(readOnly = true)
public class XaSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
@Autowired
XaCmsResourceRepository msCmsResourceRepository;
@Autowired
XaCmsRoleRepository msCmsRoleRepository;
private static Map<String, Collection<ConfigAttribute>> roleMap = null;
public void loadResourceDefine() {
if (roleMap == null) {
roleMap = new LinkedHashMap<String, Collection<ConfigAttribute>>();
}
// Iterator<XaCmsRole> iterator = msCmsRoleRepository.findAll().iterator();
Iterator<XaCmsRole> iterator = msCmsRoleRepository.findAllXaCmsRole(XaConstant.RoleStatus.status_normal).iterator();
while (iterator.hasNext()) {
XaCmsRole mcr = iterator.next();
List<String> urlList = msCmsResourceRepository
.findResourceByRoleId(mcr.getRoleId());
for (String url : urlList) {
if (XaUtil.isNotEmpty(url)) {
if (XaUtil.isNotEmpty(mcr.getRoleName())) {
ConfigAttribute configAttribute = new SecurityConfig(
mcr.getRoleName());
Collection<ConfigAttribute> configAttributes = null;
if (roleMap.containsKey(url)) {
configAttributes = roleMap.get(url);
} else {
configAttributes = new ArrayList<ConfigAttribute>();
}
configAttributes.add(configAttribute);
roleMap.put(url, configAttributes);
}
}
}
}
}
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
String url = ((FilterInvocation) object).getRequestUrl();
int firstQuestionMarkIndex = url.indexOf("?");
if (firstQuestionMarkIndex != -1) {
url = url.substring(0, firstQuestionMarkIndex);
}
if (roleMap == null) {
loadResourceDefine();
}
return roleMap.get(url);
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
public static void reset(){
roleMap = null;
}
}
同时也帖下大神的的代码
package com.nuoke;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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;
public class MyInvocationSecurityMetadataSource
implements FilterInvocationSecurityMetadataSource {
private UrlMatcher urlMatcher = new AntUrlPathMatcher();
private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
//tomcat启动时实例化一次
public MyInvocationSecurityMetadataSource() {
//这个类的实例化只在web服务器启动时调用一次,那就是说loadResourceDefine方法只会调用一次
//所以只适合页面的权限不再更改的情况。
loadResourceDefine();
}
//tomcat开启时加载一次,加载所有url和权限(或角色)的对应关系
private void loadResourceDefine() {
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
//需要ROLE_USER角色登录后才能访问的页面。
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
ConfigAttribute ca = new SecurityConfig("ROLE_USER");
atts.add(ca);
resourceMap.put("/index.jsp", atts);
resourceMap.put("/admin.jsp", atts);
//任何用户都没有进入/other.jsp权限
Collection<ConfigAttribute> attsno =new ArrayList<ConfigAttribute>();
ConfigAttribute cano = new SecurityConfig("ROLE_NO");
attsno.add(cano);
resourceMap.put("/accessDenied.jsp", attsno);
//当url有交集时,就有可能漏掉一些角色
}
//参数是要访问的url,返回这个url对于的所有权限(或角色)
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
// 将参数转为url
String url = ((FilterInvocation)object).getRequestUrl();
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
if (urlMatcher.pathMatchesUrl(resURL, url)) {
return resourceMap.get(resURL);
}
}
return null;
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
}
// 下面的内容是 自定义登录,这部分是我写的.当时的目的是 为了在登录的时候记录 登录日志。
<!-- 紫色的部分,看字面意思:就是入口。就是登录的入口 -->
<http auto-config="false" entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/index.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/m/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/commons/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/upload/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/cms/**" access="ROLE_USER"/>
<intercept-url pattern="/adminIndex.html" access="ROLE_USER"/>
<intercept-url pattern="/backstage/*.html" access="ROLE_USER"/>
<!-- <form-login login-page="/login.html"
default-target-url="/adminIndex.html" authentication-failure-url="/login.html?error=true" /> -->
<logout logout-success-url="/login.html" logout-url="/j_spring_security_logout"/>
<custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误 -->
<custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
</http>
<beans:bean id="myLoginFilter" class="com.xa3ti.qingbaosouji.base.filter.MyUsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="myAuthenticationManager"/> <!-- 登录认证 上面的部分讲到了-->
<beans:property name="authenticationFailureHandler" ref="failureHandler"/> <!--
登录失败 -->
<beans:property name="authenticationSuccessHandler" ref="successHandler"/>
<!-- 登录成功 -->
</beans:bean>
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>
<!-- //成功登录后 -->
<beans:bean id="successHandler" class="com.xa3ti.qingbaosouji.base.filter.MySavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/adminIndex.html"/>
</beans:bean>
<!-- //登录失败 -->
<beans:bean id="failureHandler" class="com.xa3ti.qingbaosouji.base.filter.MySimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.html?error=true"/>
</beans:bean>
所以都贴出来。以后如果发现又新的东西再继续添加。
这个是 spring-secrity 配置文件。 自己项目的配置
<?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.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd"> <global-method-security pre-post-annotations="enabled" /> <!-- HTTP安全配置 --> <http auto-config="false" entry-point-ref="authenticationEntryPoint"> <intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/index.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/m/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/commons/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/upload/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/cms/**" access="ROLE_USER"/> <intercept-url pattern="/adminIndex.html" access="ROLE_USER"/> <intercept-url pattern="/backstage/*.html" access="ROLE_USER"/> <!-- <form-login login-page="/login.html" default-target-url="/adminIndex.html" authentication-failure-url="/login.html?error=true" /> --> <logout logout-success-url="/login.html" logout-url="/j_spring_security_logout"/> <custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" /> <!-- //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误 --> <custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" /> </http> <beans:bean id="myLoginFilter" class="com.base.filter.MyUsernamePasswordAuthenticationFilter"> <beans:property name="authenticationManager" ref="myAuthenticationManager"/> <beans:property name="authenticationFailureHandler" ref="failureHandler"/> <beans:property name="authenticationSuccessHandler" ref="successHandler"/> </beans:bean> <beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/login.html" /> </beans:bean> <!-- //成功登录后 --> <beans:bean id="successHandler" class="com.base.filter.MySavedRequestAwareAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/adminIndex.html"/> </beans:bean> <!-- //登录失败 --> <beans:bean id="failureHandler" class="com.base.filter.MySimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login.html?error=true"/> </beans:bean> <!-- 1.URL过滤器或方法拦截器:用来拦截URL或者方法资源对其进行验证,其抽象基类为AbstractSecurityInterceptor 2.资源权限获取器:用来取得访问某个URL或者方法所需要的权限,接口为SecurityMetadataSource 3.访问决策器:用来决定用户是否拥有访问权限的关键类,其接口为AccessDecisionManager 调用顺序为:AbstractSecurityInterceptor调用SecurityMetadataSource取得资源的所有可访问权限, 然后再调用AccessDecisionManager来实现决策,确定用户是否有权限访问该资源。 --> <!-- 自定义的filter, 必须包含authenticationManager, accessDecisionManager, securityMetadataSource三个属性 qingbaosouji--> <beans:bean id="mySecurityFilter" class="com.xa3ti.qingbaosouji.base.security.XaFilterSecurityInterceptor"> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean> <!-- 取HTTP配置中的authenticationManager 设置alias别名 --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="userDetailsManager"> <password-encoder hash="md5"/> </authentication-provider> </authentication-manager> <!-- 用户详细信息管理:数据源、用户缓存(通过数据库管理用户、角色、权限、资源) --> <beans:bean id="userDetailsManager" class="com.base.security.XaUserDetailsService"> </beans:bean> <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源。 --> <beans:bean id="myAccessDecisionManager" class="com.base.security.XaAccessDecisionManagerService" /> <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色去访问。 --> <beans:bean id="mySecurityMetadataSource" init-method="loadResourceDefine" class="com.base.security.XaSecurityMetadataSourceService"> </beans:bean> </beans:beans>
这个是大神的配置
<?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.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd"> <global-method-security pre-post-annotations="enabled" /> <!-- HTTP安全配置 --> <http auto-config="false" entry-point-ref="authenticationEntryPoint"> <intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/index.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/m/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/commons/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/upload/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/cms/**" access="ROLE_USER"/> <intercept-url pattern="/adminIndex.html" access="ROLE_USER"/> <intercept-url pattern="/backstage/*.html" access="ROLE_USER"/> <!-- <form-login login-page="/login.html" default-target-url="/adminIndex.html" authentication-failure-url="/login.html?error=true" /> --> <logout logout-success-url="/login.html" logout-url="/j_spring_security_logout"/> <custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" /> <!-- //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误 --> <custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" /> </http> <beans:bean id="myLoginFilter" class="com.xa3ti.qingbaosouji.base.filter.MyUsernamePasswordAuthenticationFilter"> <beans:property name="authenticationManager" ref="myAuthenticationManager"/> <beans:property name="authenticationFailureHandler" ref="failureHandler"/> <beans:property name="authenticationSuccessHandler" ref="successHandler"/> </beans:bean> <beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/login.html" /> </beans:bean> <!-- //成功登录后 --> <beans:bean id="successHandler" class="com.xa3ti.qingbaosouji.base.filter.MySavedRequestAwareAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/adminIndex.html"/> </beans:bean> <!-- //登录失败 --> <beans:bean id="failureHandler" class="com.xa3ti.qingbaosouji.base.filter.MySimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login.html?error=true"/> </beans:bean> <!-- 1.URL过滤器或方法拦截器:用来拦截URL或者方法资源对其进行验证,其抽象基类为AbstractSecurityInterceptor 2.资源权限获取器:用来取得访问某个URL或者方法所需要的权限,接口为SecurityMetadataSource 3.访问决策器:用来决定用户是否拥有访问权限的关键类,其接口为AccessDecisionManager 调用顺序为:AbstractSecurityInterceptor调用SecurityMetadataSource取得资源的所有可访问权限, 然后再调用AccessDecisionManager来实现决策,确定用户是否有权限访问该资源。 --> <!-- 自定义的filter, 必须包含authenticationManager, accessDecisionManager, securityMetadataSource三个属性 qingbaosouji--> <beans:bean id="mySecurityFilter" class="com.xa3ti.qingbaosouji.base.security.XaFilterSecurityInterceptor"> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean> <!-- 取HTTP配置中的authenticationManager 设置alias别名 --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="userDetailsManager"> <password-encoder hash="md5"/> </authentication-provider> </authentication-manager> <!-- 用户详细信息管理:数据源、用户缓存(通过数据库管理用户、角色、权限、资源) --> <beans:bean id="userDetailsManager" class="com.xa3ti.qingbaosouji.base.security.XaUserDetailsService"> </beans:bean> <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源。 --> <beans:bean id="myAccessDecisionManager" class="com.xa3ti.qingbaosouji.base.security.XaAccessDecisionManagerService" /> <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色去访问。 --> <beans:bean id="mySecurityMetadataSource" init-method="loadResourceDefine" class="com.xa3ti.qingbaosouji.base.security.XaSecurityMetadataSourceService"> </beans:bean> </beans:beans>
然后是 <beans:bean id="mySecurityFilter" class="com.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>
下面是红色文件的内容。 这个基本使用 内容都是一样。大神的注释比较代码。这个文件一般不用修改,直接使用就好。因为大神的内容所以 文件名不一样
package com.nuoke; 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; /* * 继承AbstractSecurityInterceptor、实现Filter是必须的。 首先,登陆后,每次访问资源都会被这个拦截器拦截,会执行doFilter这个方法, 这个方法调用了invoke方法,其中fi断点显示是一个url(可能重写了toString方法吧,但是里面还有一些方法的),最重要的是beforeInvocation这个方法, 它首先会调用MyInvocationSecurityMetadataSource类的getAttributes方法获取被拦截url所需的权限, then调用MyAccessDecisionManager类decide方法判断用户是否够权限。弄完这一切就会执行下一个拦截器. */ public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { //配置文件注入 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 FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { return this.securityMetadataSource; } @Override public Class<? extends Object> getSecureObjectClass() { return FilterInvocation.class; } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi里面有一个被拦截的url //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); try { //执行下一个拦截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } public void setSecurityMetadataSource( FilterInvocationSecurityMetadataSource newSource) { this.securityMetadataSource = newSource; } public void destroy() { } public void init(FilterConfig arg0) throws ServletException { } }
<beans:bean id="mySecurityFilter" class="com.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>
然后是绿色部分的代码。我项目中使用。
首先是 ref 配置
<!-- 取HTTP配置中的authenticationManager 设置alias别名 --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="userDetailsManager"> <password-encoder hash="md5"/> </authentication-provider> </authentication-manager>
<!-- 用户详细信息管理:数据源、用户缓存(通过数据库管理用户、角色、权限、资源) --> <beans:bean id="userDetailsManager" class="com.base.security.XaUserDetailsService"> </beans:bean>
package com.base.security; import java.util.ArrayList; import java.util.List; 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.stereotype.Service; import com.base.constant.XaConstant; import com.base.entity.XaCmsUser; import com.base.exception.LoginLockException; import com.base.repository.XaCmsUserRepository; import com.base.util.DateProcessUtil; /** * 登录权限验证service * @author zj * */ @Service("MsUserDetailsService") public class XaUserDetailsService implements UserDetailsService { protected static final String ROLE_PREFIX = "ROLE_"; protected static final GrantedAuthority DEFAULT_USER_ROLE = new SimpleGrantedAuthority(ROLE_PREFIX + "USER"); @Autowired XaCmsUserRepository xaCmsUserRepository; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { XaUserDetails msUserDetails = new XaUserDetails(); try { XaCmsUser user; List<XaCmsUser> userList = xaCmsUserRepository.findByUserName(new String(username.getBytes("ISO-8859-1"),"UTF-8")); if(userList.size() > 0 && userList.get(0).getStatus() == XaConstant.UserStatus.status_lock){ throw new LoginLockException("您输入的账号已被锁定"); } /*if(userList.size() > 0 && userList.get(0).getIsAdmin() != 1){ throw new LoginAdminException("您的账号不是管理员"); }*/ if(userList.size() > 0 && userList.get(0) != null){ user = userList.get(0); user.setLastLoginDate(DateProcessUtil.getToday(DateProcessUtil.YYYYMMDDHHMMSS)); xaCmsUserRepository.save(user); msUserDetails.setUsername(user.getUserName()); msUserDetails.setPassword(user.getPassword()); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); GrantedAuthority authority = new SimpleGrantedAuthority(user.getRole().getRoleName()); authorities.add(authority); //设置用户oauth通过token访问的权限 authorities.add(DEFAULT_USER_ROLE); authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + "UNITY")); authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + "MOBILE")); msUserDetails.setAuthorities(authorities); } } catch (Exception e) { e.printStackTrace(); } return msUserDetails; } }
然后是<beans:bean id="mySecurityFilter" class="com.xa3ti.qingbaosouji.base.security.XaFilterSecurityInterceptor"> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean><!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源。 -->
<beans:bean id="myAccessDecisionManager"
class="com.base.security.XaAccessDecisionManagerService" />
package com.base.security; 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.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service("MsAccessDecisionManagerService") @Transactional(readOnly = true) public class XaAccessDecisionManagerService implements AccessDecisionManager {//检查用户是否够权限访问资源
//参数authentication是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息
//参数object是url
//参数configAttributes所需的权限
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) {
return;
}
Iterator<ConfigAttribute> iterator = configAttributes.iterator();
while (iterator.hasNext()) {
ConfigAttribute configAttribute = iterator.next();
String needPermission = configAttribute.getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needPermission.equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("没有权限访问");
}
public boolean supports(ConfigAttribute attribute) {
// TODO Auto-generated method stub
return true;
}
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
}
<beans:bean id="mySecurityFilter" class="com.xa3ti.qingbaosouji.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"
/>
</beans:bean>
<!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色去访问。 --> <beans:bean id="mySecurityMetadataSource" init-method="loadResourceDefine" class="com.base.security.XaSecurityMetadataSourceService"> </beans:bean>
package com.base.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.base.constant.XaConstant;
import com.base.entity.XaCmsRole;
import com.base.repository.XaCmsResourceRepository;
import com.base.repository.XaCmsRoleRepository;
import com.base.util.XaUtil;
@Service("MsSecurityMetadataSourceService")
@Transactional(readOnly = true)
public class XaSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
@Autowired
XaCmsResourceRepository msCmsResourceRepository;
@Autowired
XaCmsRoleRepository msCmsRoleRepository;
private static Map<String, Collection<ConfigAttribute>> roleMap = null;
public void loadResourceDefine() {
if (roleMap == null) {
roleMap = new LinkedHashMap<String, Collection<ConfigAttribute>>();
}
// Iterator<XaCmsRole> iterator = msCmsRoleRepository.findAll().iterator();
Iterator<XaCmsRole> iterator = msCmsRoleRepository.findAllXaCmsRole(XaConstant.RoleStatus.status_normal).iterator();
while (iterator.hasNext()) {
XaCmsRole mcr = iterator.next();
List<String> urlList = msCmsResourceRepository
.findResourceByRoleId(mcr.getRoleId());
for (String url : urlList) {
if (XaUtil.isNotEmpty(url)) {
if (XaUtil.isNotEmpty(mcr.getRoleName())) {
ConfigAttribute configAttribute = new SecurityConfig(
mcr.getRoleName());
Collection<ConfigAttribute> configAttributes = null;
if (roleMap.containsKey(url)) {
configAttributes = roleMap.get(url);
} else {
configAttributes = new ArrayList<ConfigAttribute>();
}
configAttributes.add(configAttribute);
roleMap.put(url, configAttributes);
}
}
}
}
}
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
String url = ((FilterInvocation) object).getRequestUrl();
int firstQuestionMarkIndex = url.indexOf("?");
if (firstQuestionMarkIndex != -1) {
url = url.substring(0, firstQuestionMarkIndex);
}
if (roleMap == null) {
loadResourceDefine();
}
return roleMap.get(url);
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
public static void reset(){
roleMap = null;
}
}
同时也帖下大神的的代码
package com.nuoke;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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;
public class MyInvocationSecurityMetadataSource
implements FilterInvocationSecurityMetadataSource {
private UrlMatcher urlMatcher = new AntUrlPathMatcher();
private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
//tomcat启动时实例化一次
public MyInvocationSecurityMetadataSource() {
//这个类的实例化只在web服务器启动时调用一次,那就是说loadResourceDefine方法只会调用一次
//所以只适合页面的权限不再更改的情况。
loadResourceDefine();
}
//tomcat开启时加载一次,加载所有url和权限(或角色)的对应关系
private void loadResourceDefine() {
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
//需要ROLE_USER角色登录后才能访问的页面。
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
ConfigAttribute ca = new SecurityConfig("ROLE_USER");
atts.add(ca);
resourceMap.put("/index.jsp", atts);
resourceMap.put("/admin.jsp", atts);
//任何用户都没有进入/other.jsp权限
Collection<ConfigAttribute> attsno =new ArrayList<ConfigAttribute>();
ConfigAttribute cano = new SecurityConfig("ROLE_NO");
attsno.add(cano);
resourceMap.put("/accessDenied.jsp", attsno);
//当url有交集时,就有可能漏掉一些角色
}
//参数是要访问的url,返回这个url对于的所有权限(或角色)
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
// 将参数转为url
String url = ((FilterInvocation)object).getRequestUrl();
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
if (urlMatcher.pathMatchesUrl(resURL, url)) {
return resourceMap.get(resURL);
}
}
return null;
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
}
// 下面的内容是 自定义登录,这部分是我写的.当时的目的是 为了在登录的时候记录 登录日志。
<!-- 紫色的部分,看字面意思:就是入口。就是登录的入口 -->
<http auto-config="false" entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/index.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/m/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/commons/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/upload/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/cms/**" access="ROLE_USER"/>
<intercept-url pattern="/adminIndex.html" access="ROLE_USER"/>
<intercept-url pattern="/backstage/*.html" access="ROLE_USER"/>
<!-- <form-login login-page="/login.html"
default-target-url="/adminIndex.html" authentication-failure-url="/login.html?error=true" /> -->
<logout logout-success-url="/login.html" logout-url="/j_spring_security_logout"/>
<custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误 -->
<custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
</http>
<beans:bean id="myLoginFilter" class="com.xa3ti.qingbaosouji.base.filter.MyUsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="myAuthenticationManager"/> <!-- 登录认证 上面的部分讲到了-->
<beans:property name="authenticationFailureHandler" ref="failureHandler"/> <!--
登录失败 -->
<beans:property name="authenticationSuccessHandler" ref="successHandler"/>
<!-- 登录成功 -->
</beans:bean>
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>
<!-- //成功登录后 -->
<beans:bean id="successHandler" class="com.xa3ti.qingbaosouji.base.filter.MySavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/adminIndex.html"/>
</beans:bean>
<!-- //登录失败 -->
<beans:bean id="failureHandler" class="com.xa3ti.qingbaosouji.base.filter.MySimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.html?error=true"/>
</beans:bean>
package com.base.filter; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import com.base.entity.XaCmsUser; import com.business.entity.RoleLogger; import com.business.service.RoleLoggerService; public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{ @Autowired private RoleLoggerService roleLoggerService; /* (non-Javadoc) * @see org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication) */ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub //记录登录日志 saveLoginInfo(request,authentication); super.onAuthenticationSuccess(request, response, authentication); } @Transactional(readOnly=false) public void saveLoginInfo(HttpServletRequest request,Authentication authentication){ //XaCmsUser user = (XaCmsUser)authentication.getPrincipal(); Object ob = authentication.getPrincipal(); try { //String ip = this.getIpAddress(request); RoleLogger rl = new RoleLogger(); rl.setRoleId(SecurityContextHolder.getContext().getAuthentication().getName()); rl.setHandleType("登录"); roleLoggerService.createRoleLogger(null, rl); } catch (Exception e) { if(logger.isWarnEnabled()){ logger.info("无法更新用户登录信息至数据库"); } } } public String getIpAddress(HttpServletRequest request){ String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } private RequestCache requestCache = new HttpSessionRequestCache(); }
package com.base.filter; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.WebAttributes; import org.springframework.security.web.authentication.AuthenticationFailureHandler; public class MySimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler{ private String defaultFailureUrl; private boolean forwardToDestination = false; private boolean allowSessionCreation = true; private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); /* @Value(value = "${local.service.url}") private String LOCAL_SERVER_URL; */ public MySimpleUrlAuthenticationFailureHandler() { } public MySimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) { setDefaultFailureUrl(defaultFailureUrl); } /** * Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a 401 error code. * <p> * If redirecting or forwarding, {@code saveException} will be called to cache the exception for use in * the target view. */ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { //认证失败区别前后台:LOGIN URL if(request.getParameter("spring-security-redirect") != null){ request.getSession().setAttribute("callUrlFailure", request.getParameter("spring-security-redirect")); } //若有loginUrl 则重定向到后台登录界面 if(request.getParameter("loginUrl") != null && !"".equals(request.getParameter("loginUrl"))){ //defaultFailureUrl = LOCAL_SERVER_URL+"/backlogin.html?validated=false"; defaultFailureUrl = "/login.html?error=true"; } //defaultFailureUrl 默认的认证失败回调URL if (defaultFailureUrl == null) { //logger.debug("No failure URL set, sending 401 Unauthorized error"); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage()); } else { saveException(request, exception); if (forwardToDestination) { //logger.debug("Forwarding to " + defaultFailureUrl); request.getRequestDispatcher(defaultFailureUrl).forward(request, response); } else { //logger.debug("Redirecting to " + defaultFailureUrl); redirectStrategy.sendRedirect(request, response, defaultFailureUrl); } } } /** * Caches the {@code AuthenticationException} for use in view rendering. * <p> * If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store * the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session * will be created. Otherwise the exception will not be stored. */ protected final void saveException(HttpServletRequest request, AuthenticationException exception) { if (forwardToDestination) { request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } else { HttpSession session = request.getSession(false); if (session != null || allowSessionCreation) { request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } } } /** * The URL which will be used as the failure destination. * * @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp". */ public void setDefaultFailureUrl(String defaultFailureUrl) { this.defaultFailureUrl = defaultFailureUrl; } protected boolean isUseForward() { return forwardToDestination; } /** * If set to <tt>true</tt>, performs a forward to the failure destination URL instead of a redirect. Defaults to * <tt>false</tt>. */ public void setUseForward(boolean forwardToDestination) { this.forwardToDestination = forwardToDestination; } /** * Allows overriding of the behaviour when redirecting to a target URL. */ public void setRedirectStrategy(RedirectStrategy redirectStrategy) { this.redirectStrategy = redirectStrategy; } protected RedirectStrategy getRedirectStrategy() { return redirectStrategy; } protected boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } }
相关文章推荐
- el表达式 分页 Struts2后台
- SSH学习(六)Struts2拦截器
- Java 中 byte、byte 数组和 int、long 之间的转换
- org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML doc
- sping 乱码
- Struts2实现文件上传和下载
- struts2 namespace
- java文件引用 提示包不存在
- java 爬虫
- 网页数据抓取之淘宝数据
- RxJava学习经验谈——map与flatmap
- spring学习笔记1
- Java 责任链模式
- Java getDeclared××× 方法和 get××× 方法的区别
- Java 8 flatMap example
- 操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)
- spring security基础配置(一)
- java 等待所有线程执行完毕
- JAVA经典排序算法总结
- Spring+Struts2+hibernate快速使用