准备工作:数据库采用mysql(5.6及以上)

CREATE TABLE `auth_system` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`NAME` varchar(100) DEFAULT NULL COMMENT '系统名称',
`URL` varchar(100) DEFAULT NULL COMMENT '系统地址',
`description` varchar(100) DEFAULT NULL COMMENT '描述',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='认证系统表';

CREATE TABLE `auth_user` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`USERNAME` varchar(100) NOT NULL COMMENT '用户名',
`NAME` varchar(100) DEFAULT NULL COMMENT '用户姓名',
`PASSWORD` varchar(500) NOT NULL COMMENT '密码',
`LAST_LOGIN` datetime DEFAULT NULL COMMENT '最后登录日期',
`DEADLINE` datetime DEFAULT NULL COMMENT '截止日期',
`LOGIN_IP` varchar(100) DEFAULT NULL COMMENT '最后登录IP',
`ENABLED` char(1) DEFAULT NULL COMMENT 'ENABLED',
`ACCOUNT_NON_EXPIRED` char(1) DEFAULT NULL COMMENT '是否过期',
`ACCOUNT_NON_LOCKED` char(1) DEFAULT NULL COMMENT '是否锁定',
`CREDENTIALS_NON_EXPIRED` char(1) DEFAULT NULL COMMENT '用户证书是否有效',
`SYSTEM_ID` int(11) DEFAULT NULL COMMENT '系统ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8 COMMENT='认证用户表';

CREATE TABLE `auth_user_role` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`ROLE_ID` int(11) NOT NULL COMMENT '角色ID',
`USER_ID` int(11) NOT NULL COMMENT '用户ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=266 DEFAULT CHARSET=utf8 COMMENT='认证用户角色表';

CREATE TABLE `auth_role` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`ROLE_NAME` varchar(100) DEFAULT NULL COMMENT '角色名称',
`ROLE_DESC` varchar(200) DEFAULT NULL COMMENT '角色描述',
`ENABLE` int(11) DEFAULT NULL COMMENT '启用状态',
`ISSYS` int(11) DEFAULT NULL COMMENT 'ISSYS',
`MODULE_ID` varchar(100) DEFAULT NULL COMMENT '模块ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
`SYSTEM_ID` int(11) DEFAULT NULL COMMENT '系统ID',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=119 DEFAULT CHARSET=utf8 COMMENT='认证角色表';

CREATE TABLE `auth_role_authority` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`ROLE_ID` int(11) NOT NULL COMMENT '角色ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
`AUTHORITY_ID` int(11) NOT NULL COMMENT '权限ID',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=159 DEFAULT CHARSET=utf8 COMMENT='认证角色权限表';

CREATE TABLE `auth_authority` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`AUTHORITY_MARK` varchar(100) DEFAULT NULL COMMENT '权限标示',
`AUTHORITY_NAME` varchar(100) NOT NULL COMMENT '权限名称',
`AUTHORITY_DESC` varchar(200) DEFAULT NULL COMMENT '权限描述',
`MESSAGE` varchar(100) DEFAULT NULL COMMENT '提示信息',
`ENABLE` char(1) DEFAULT NULL COMMENT 'ENABLE',
`ISSYS` char(1) DEFAULT NULL COMMENT 'ISSYS',
`MODULE_ID` int(11) DEFAULT NULL COMMENT '模块ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
`SYSTEM_ID` int(11) DEFAULT NULL COMMENT '系统ID',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=111 DEFAULT CHARSET=utf8 COMMENT='认证权限表';

CREATE TABLE `auth_authority_resource` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`RESOURCE_ID` int(11) NOT NULL COMMENT '资源ID',
`AUTHORITY_ID` int(11) NOT NULL COMMENT '权限ID',
`CREATED_DT` datetime DEFAULT NULL COMMENT '创建时间',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`ID`),
KEY `FK_SYS_AUTH_REFERENCE_SYS_AUTH` (`AUTHORITY_ID`),
KEY `FK_SYS_AUTH_REFERENCE_SYS_RESO` (`RESOURCE_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6112 DEFAULT CHARSET=utf8 COMMENT='认证权限资源表';

CREATE TABLE `auth_resource` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '资源ID',
`RESOURCE_TYPE` varchar(100) DEFAULT NULL COMMENT '资源类型',
`RESOURCE_NAME` varchar(100) DEFAULT NULL COMMENT '资源名称',
`RESOURCE_DESC` varchar(200) DEFAULT NULL COMMENT '资源描述',
`RESOURCE_PATH` varchar(200) DEFAULT NULL COMMENT '资源路径',
`PRIORITY` varchar(100) DEFAULT NULL COMMENT '优先次序',
`ENABLE` char(1) DEFAULT NULL COMMENT 'ENABLE',
`ISSYS` char(1) DEFAULT NULL COMMENT 'ISSYS',
`MODULE_ID` varchar(100) DEFAULT NULL COMMENT '模块ID',
`create_dt` datetime DEFAULT NULL COMMENT 'create_dt',
`create_by` int(11) DEFAULT NULL COMMENT 'create_by',
`last_update_dt` datetime DEFAULT NULL COMMENT '最后更新时间',
`last_update_by` int(11) DEFAULT NULL COMMENT '最后更新人',
`sts` char(1) DEFAULT NULL COMMENT '状态',
`SYSTEM_ID` int(11) DEFAULT NULL COMMENT '系统ID',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=550 DEFAULT CHARSET=utf8 COMMENT='认证资源表';

主要用到以上这些表,准备工作完毕,开始进入正题

要使用spring security来作为权限控制,在完成如上的数据库设计后,

采用maven作为构建工具:

<spring.security.version>3.2.6.RELEASE</spring.security.version>
<!--spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
<exclusions>
<exclusion>
<artifactId>spring-asm</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>

在web.xml中加上

<!--security-->
<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> 该配置作用是让spring security对所有请求进行拦截, 我们需要加一个spring的配置文件 application-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
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
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
"> <bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:security.properties</value>
</property>
</bean> <!-- 配置不过滤的资源(静态资源及登录相关) -->
<sec:http pattern="/**/*.css" security="none"></sec:http>
<sec:http pattern="/**/*.jpg" security="none"></sec:http>
<sec:http pattern="/**/*.jpeg" security="none"></sec:http>
<sec:http pattern="/**/*.gif" security="none"></sec:http>
<sec:http pattern="/**/*.png" security="none"></sec:http>
<sec:http pattern="/**/*.js" security="none"></sec:http>
<sec:http pattern="/static/**" security="none"></sec:http> <sec:http pattern="/login" security="none"></sec:http> <bean id="customUserDetailsService" class="com.linxingall.auth.security.DefaultUserDetailsService"></bean>
<bean id="authenticationSuccessHandler" class="com.linxingall.auth.security.SimpleLoginSuccessHandler">
<property name="defaultTargetUrl" value="${success.url}"></property>
<property name="forwardToDestination" value="false"></property>
</bean>
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login" />
</bean>
<sec:http access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint"> <sec:access-denied-handler ref="accessDeniedHandler"/> <sec:session-management invalid-session-url="/login" />
<sec:custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
<sec:custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"/>
<sec:custom-filter ref="rememberMeFilter" position="REMEMBER_ME_FILTER"/>
<sec:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
</sec:http> <bean id="rememberMeFilter"
class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<!-- RememberMeServices的实现 -->
<bean id="rememberMeServices"
class="com.linxingall.auth.security.CustomTokenBasedRememberMeServices">
<property name="userDetailsService" ref="customUserDetailsService" />
<property name="tokenValiditySeconds" value="43200"/>
<property name="key" value="abcd"/>
<property name="cookieName" value="remember_me"/>
<!-- 指定request中包含的用户是否选择了记住我的参数名 -->
<property name="parameter" value="remember_me"/>
<property name="alwaysRemember" value="true"/>
<property name="rootPath" value="false"/>
</bean>
<!-- key值需与对应的RememberMeServices保持一致 -->
<bean id="rememberMeAuthenticationProvider"
class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="abcd" />
</bean> <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<property name="filterProcessesUrl" value="/logout"/>
<constructor-arg index="0" value="/login"/>
<constructor-arg index="1">
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"></bean>
<bean class="com.linxingall.auth.security.CustomCookieClearingLogoutHandler">
<constructor-arg>
<list>
<value>JSESSIONID</value>
<value>JSESSIONID</value>
<value>JSESSIONID</value>
<value>remember_me</value>
</list>
</constructor-arg>
<property name="splitChar" value="@"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="loginFilter" class="com.linxingall.auth.security.DefaultUsernamePasswordAuthenticationFilter">
<property name="usernameParameter" value="username"></property>
<property name="passwordParameter" value="password"></property>
<property name="filterProcessesUrl" value="/login.do"></property>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationFailureHandler">
<bean class="com.linxingall.auth.security.CustomUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login"></property>
</bean>
</property>
</bean>
<bean id="filterSecurityInterceptor" class="com.linxingall.auth.security.CustomFilterSecurityInterceptor">
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="securityMetadataSource" ref="securityMetadataSource" />
</bean> <bean id="securityMetadataSource"
class="com.linxingall.auth.security.URLFilterInvocationSecurityMetadataSource"/> <!-- 自定义权限不足处理程序 -->
<bean id="accessDeniedHandler" class="com.linxingall.auth.security.DefaultAccessDeniedHandler">
<property name="errorPage" value="/403"></property>
</bean> <sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="authenticationProvider" />
<sec:authentication-provider ref="rememberMeAuthenticationProvider"/>
</sec:authentication-manager> <bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="hideUserNotFoundExceptions" value="false" />
<property name="userDetailsService" ref="customUserDetailsService" />
<property name="passwordEncoder" ref="passwordEncode" />
<!--<property name="saltSource" ref="saltSource" />-->
</bean> <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg name="decisionVoters">
<list>
<ref bean="roleVoter"/>
<ref bean="authenticatedVoter"/>
</list>
</constructor-arg>
</bean> <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value=""></property>
</bean> <bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter" /> <!-- 配置密码加密类 -->
<bean id="passwordEncode" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> <!--<bean id="passwordEncode" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />-->
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="username"/>
</bean> </beans>
接下来为java类;
DefaultUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
重写
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
if (!CaptchaServiceSingleton.getInstance().validateResponseForID(request.getSession().getId(), request.getParameter("validateCode"))) {
throw new CaptchaException("");
}
} catch (CaptchaServiceException e) {
throw new CaptchaException("");
}
//校验是否拥有当前系统访问权限
if(!userService.hasSystemPermistion(this.obtainUsername(request),request.getRequestURI(),request.getContextPath())){
throw new AuthenticationServiceException("");
}
return super.attemptAuthentication(request, response);
}
UserService
@Override
public boolean hasSystemPermistion(String userName, String requestUrl, String basePath) {
Preconditions.checkArgument(StringUtils.isNotBlank(userName),"user name cannot be null!");
List<UserDo> userDos = getUserDo(userName);
if(CollectionUtils.isNotEmpty(userDos)){
Integer systemId = userDos.get(0).getSystemId();
//用户未配置系统默认能登陆所有系统
if(systemId!=null){
AuthSystemDo authSystemDo = authSystemDao.selectByPrimaryKey(systemId);
if(authSystemDo!=null){
String systemUrl = authSystemDo.getUrl();
if(StringUtils.startsWith(systemUrl,"/")){
//网址配置“/”开头的系统比较上下文路径
if (!StringUtils.equals(basePath,systemUrl)) {
return false;
}
}else{
//其他比较全网址是否以系统配置的网址开头
if(!StringUtils.startsWith(requestUrl,systemUrl)){
return false;
}
}
}
}
}else{
//用户不存在 返回无权限
return false;
}
return true;
} CustomTokenBasedRememberMeServices 

public class CustomTokenBasedRememberMeServices extends TokenBasedRememberMeServices implements MessageSourceAware {

protected MessageSourceAccessor message;

@Autowired
private UserService userService;

private boolean rootPah = false;

public boolean isRootPah() {
return rootPah;
}

public void setRootPah(boolean rootPah) {
this.rootPah = rootPah;
}

@Override
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) {
if(cookieTokens.length != 3) {
throw new InvalidCookieException("Cookie token did not contain 3 tokens, but contained \'" + Arrays.asList(cookieTokens) + "\'");
}
//校验是否拥有当前系统访问权限
if(!userService.hasSystemPermistion(cookieTokens[0],request.getRequestURI(),request.getContextPath())){
throw new AccessDeniedException(this.message.getMessage("custom.error.auth.system.error"
,new String[]{cookieTokens[0]}));
}
return super.processAutoLoginCookie(cookieTokens, request, response);
}

@Override
protected void setCookie(String[] tokens, int maxAge, HttpServletRequest request, HttpServletResponse response) {
String cookieValue = this.encodeCookie(tokens);
Cookie cookie = new Cookie(this.getCookieName(), cookieValue);
if(hasRememberMeParam(request,this.getParameter())) {
cookie.setMaxAge(maxAge);
}
if(this.rootPah){
cookie.setPath("/");
}else {
cookie.setPath(this.getCookiePath(request));
}
if (maxAge < 1) {
cookie.setVersion(1);
}
cookie.setSecure(request.isSecure());
//ReflectionUtils.invokeMethod(this.setHttpOnlyMethod, cookie, new Object[]{Boolean.TRUE});
response.addCookie(cookie);
}
@Override
protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) {
this.logger.debug("Cancelling cookie");
Cookie cookie = new Cookie(this.getCookieName(), (String)null);
cookie.setMaxAge(0);
if(this.rootPah) {
cookie.setPath("/");
}else{
cookie.setPath(this.getCookiePath(request));
}
response.addCookie(cookie);
}

protected boolean hasRememberMeParam(HttpServletRequest request, String parameter) {
String paramValue = request.getParameter(parameter);
if(paramValue != null && (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") || paramValue.equalsIgnoreCase("yes") || paramValue.equals("1"))) {
return true;
} else {
return false;
}
}
private String getCookiePath(HttpServletRequest request) {
String contextPath = request.getContextPath();
return contextPath.length() > 0?contextPath:"/";
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.message = new MessageSourceAccessor(messageSource) ;
}
}


CustomCookieClearingLogoutHandler
public class CustomCookieClearingLogoutHandler implements LogoutHandler {
private String splitChar ="/";
private final List<String> cookiesToClear; public CustomCookieClearingLogoutHandler(String... cookiesToClear) {
Assert.notNull(cookiesToClear, "List of cookies cannot be null");
this.cookiesToClear = Arrays.asList(cookiesToClear);
} public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Iterator i$ = this.cookiesToClear.iterator(); while(i$.hasNext()) {
String cookieName = (String)i$.next();
String cookiePath = request.getContextPath(); if(StringUtils.indexOf(cookieName, splitChar)>0){
cookiePath = cookieName.split(splitChar)[1];
cookieName = cookieName.split(splitChar)[0];
} Cookie cookie = new Cookie(cookieName, (String)null); cookie.setPath(cookiePath);
cookie.setMaxAge(0);
response.addCookie(cookie);
} }
private String getCookiePath(HttpServletRequest request,String cookieName){
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if(cookie!=null && StringUtils.equals(cookieName,cookie.getName())){
if(StringUtils.isNotBlank(cookie.getPath())){
return cookie.getPath();
}
}
}
return "/";
} public void setSplitChar(String splitChar) {
this.splitChar = splitChar;
}
}
CustomFilterSecurityInterceptor
public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
} public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
} @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
FilterInvocation fileInvocation = new FilterInvocation(servletRequest, servletResponse, filterChain);
InterceptorStatusToken interceptorStatusToken = this
.beforeInvocation(fileInvocation);
fileInvocation.getChain().doFilter(servletRequest, servletResponse);
this.afterInvocation(interceptorStatusToken, null);
} @Override
public void destroy() { } @Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
} @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
}
URLFilterInvocationSecurityMetadataSource
public class URLFilterInvocationSecurityMetadataSource implements
FilterInvocationSecurityMetadataSource,InitializingBean {
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
protected final Log logger = LogFactory.getLog(getClass()); //权限集合
private Map<RequestMatcher, Collection<ConfigAttribute>> ALL_RESOURCE_AUTHORITIS; @Autowired
private ResourceDao resourceDao; /* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#getAttributes(java.lang.Object)
*/
@Override
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
final HttpServletRequest request = ((FilterInvocation) object).getRequest(); Collection<ConfigAttribute> attrs = Lists.newArrayList(); for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : ALL_RESOURCE_AUTHORITIS.entrySet()) {
if (entry.getKey().matches(request)) {
attrs.addAll(entry.getValue());
}
}
logger.info("URL资源:"+request.getRequestURI()+ " -> " + attrs);
if(CollectionUtils.isEmpty(attrs)){
throw new AccessDeniedException(this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
return attrs;
} /* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#getAllConfigAttributes()
*/
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : ALL_RESOURCE_AUTHORITIS.entrySet()) {
allAttributes.addAll(entry.getValue());
}
return allAttributes;
} /* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
} private Map<RequestMatcher, Collection<ConfigAttribute>> getResourceAuthoritis(){
Map<RequestMatcher, Collection<ConfigAttribute>> resultMap = Maps.newHashMap();
List<ResourceAuthDo> list = resourceDao.listAllResourceAuths();
for (ResourceAuthDo resourceAuthDo : list) {
CustomAntPathRequestMatcher matcher = new CustomAntPathRequestMatcher(resourceAuthDo.getResourcePath(),resourceAuthDo.getSystemUrl());
if(resultMap.containsKey(matcher)){
resultMap.get(matcher).add(new SecurityConfig(resourceAuthDo.getAuthorityMark()));
}else{
resultMap.put(matcher, SecurityConfig.createList(resourceAuthDo.getAuthorityMark()));
}
}
return resultMap;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
* 初始化权限列表
*/
@Override
public void afterPropertiesSet() throws Exception {
refreshResourceAuthoritis();
} public void refreshResourceAuthoritis(){
this.ALL_RESOURCE_AUTHORITIS = this.getResourceAuthoritis();
}
}
DefaultAccessDeniedHandler
public class DefaultAccessDeniedHandler implements AccessDeniedHandler {
/* (non-Javadoc)
* @see org.springframework.security.web.access.AccessDeniedHandler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.access.AccessDeniedException)
*/
private String errorPage; //~ Methods ======================================================================================================== public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
throws IOException, ServletException {
boolean isAjax = ControllerUtils.isAjaxRequest(request);
if(isAjax){
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter(); JSONObject message = new JSONObject();
message.put("code","403");
message.put("message",accessDeniedException.getMessage());
writer.print(message.toString());
}else if (!response.isCommitted()) {
if (errorPage != null) {
// Put exception into request scope (perhaps of use to a view)
request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException); // Set the 403 status code.
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // forward to error page.
RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
//将错误信息设置至请求头上
request.setAttribute("message",accessDeniedException.getMessage());
dispatcher.forward(request, response);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
}
}
} /**
* The error page to use. Must begin with a "/" and is interpreted relative to the current context root.
*
* @param errorPage the dispatcher path to display
*
* @throws IllegalArgumentException if the argument doesn't comply with the above limitations
*/
public void setErrorPage(String errorPage) {
if ((errorPage != null) && !errorPage.startsWith("/")) {
throw new IllegalArgumentException("errorPage must begin with '/'");
} this.errorPage = errorPage;
}
}
												

用户权限模块之spring security的更多相关文章

  1. Spring Boot + Spring Cloud 实现权限管理系统 (Spring Security 版本 )

    技术背景 到目前为止,我们使用的权限认证框架是 Shiro,虽然 Shiro 也足够好用并且简单,但对于 Spring 官方主推的安全框架 Spring Security,用户群也是甚大的,所以我们这 ...

  2. Django中用户权限模块

    Django中用户权限模块 1 auth模块 auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理. auth可以和admin模块配合使用, 快速建立网站的管理系 ...

  3. 030 SSM综合练习06--数据后台管理系统--SSM权限操作及Spring Security入门

    1.权限操作涉及的三张表 (1)用户表信息描述users sql语句: CREATE TABLE users ( id ) DEFAULT SYS_GUID () PRIMARY KEY, email ...

  4. 权限控制框架Spring Security 和Shiro 的总结

    关于权限控制,一开始感觉比较难,后来先是接触了Spring Security 学起来也比较吃力,再是学习了Shiro,感觉简单很多. 总体来说这些框架,主要做了两个事情 Authentication: ...

  5. Spring安全权限管理(Spring Security)

    1.spring Security简要介绍 Spring Security以前叫做acegi,是后来才成为Spring的一个子项目,也是目前最为流行的一个安全权限管理框架,它与Spring紧密结合在一 ...

  6. 【权限管理系统】Spring security(三)---认证过程(原理解析,demo)

      在前面两节Spring security (一)架构框架-Component.Service.Filter分析和Spring Security(二)--WebSecurityConfigurer配 ...

  7. 【权限管理】Spring Security 执行流程

    转自:https://blog.csdn.net/weixin_37689658/article/details/92752890 1.基本配置使用 (1)创建配置类 创建一个配置类SecurityC ...

  8. 用户权限模块之oauth2.0

    主要是在springsecurity上面扩展即可,所以内容也是基于上一个, sql: CREATE TABLE `auth_access_token` ( `id` int(11) NOT NULL ...

  9. 给Elasticsearch 5.2.2 设置用户权限 how to setting security for elasticsearch on windows

    1. download the plugin of elasticsearch: 下载 readonlyrest-1.14.0_es5.2.2.zip 2. install readonlyrest ...

随机推荐

  1. JQuery实现通过点击标题切换字体

    这个主要通过判断被点击的元素的子元素中是否包含了b元素来进行字体的切换,其中wrapInner函数是为了在$author元素的内部添加b标签. 切换回正常字体是通过将内容转化为纯文本形式,再替换元素内 ...

  2. 基于vue2.0前端组件库element中 el-form表单 自定义验证填坑

    eleme写的基于vue2.0的前端组件库: http://element.eleme.io 我在平时使用过程中,遇到的问题. 自定义表单验证出坑: 1: validate/resetFields 未 ...

  3. 自坑实录 - Asp.net MVC中无法使用@Ajax.BeginForm问题解决

    创建空的web项目,通过Nuget引用mvc组件来搭建空的MVC项目时, 在视图页面中无法使用@Ajax.BegForm来进行异步提交数据, 而新建默认的MVC模板项目却能够正常使用@Ajax.Beg ...

  4. Fail-Fast机制详解

    Java中的Iterator非常方便地为所有的数据源提供了一个统一的数据读取(删除)的接口,但是在使用的时候容易报如下错误ConcurrentModificationException,原因是在使用迭 ...

  5. 浅谈RSA加密

    RSA背景 在1976年以前,传统的加解密过程是: 1.A采用某种手段对数据进行加密. 2.数据传输到B的手中. 3.B逆向的实施A加密采用的步骤. 4.数据被还原. 这就是所谓的对称加密. 解密和加 ...

  6. HDU1829(种类并查集)

    ps:本来是想找个二分图判断的题来写,结果百度到这鬼题 Problem Description Background Professor Hopper is researching the sexua ...

  7. 瀑布流布局使用详解——JQuery插件Isotope(动态实现子项目筛选)

    瀑布流布局,听起来听牛逼的样子,其实就是简单的子元素筛选功能.不过这一功能在网站页面布局当中还是很常用的,特别是在电商网站中 经常会有点一个钮筛选,然后页面的子元素刷的以下变了样.接下来,我们先简单介 ...

  8. Kotlin学习第一课:从对比Java开始

    1. 介绍 今年初,甲骨文再次对谷歌所谓的安卓侵权使用Java提起诉讼,要求后者赔偿高达90亿美元.随后便传出谷歌因此计划将主力语言切换到苹果主导的Swift,不过这事后来没了跟进. 但谷歌在这两天的 ...

  9. 利用JavaScript数组动态写入HTML数据节点

    如果想要使用数组来写入HTML数据,绝对需要的是一个Key值,由Key来引导遍历数组各项:此外,使用DOM原生方法写入文档,用同一个CSS样式渲染它们,这样可以极大地减少开发时间和减少维护成本,此方法 ...

  10. 微信小程序大全(上)(最新整理 建议收藏)