用户权限模块之spring security
准备工作:数据库采用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的更多相关文章
- Spring Boot + Spring Cloud 实现权限管理系统 (Spring Security 版本 )
技术背景 到目前为止,我们使用的权限认证框架是 Shiro,虽然 Shiro 也足够好用并且简单,但对于 Spring 官方主推的安全框架 Spring Security,用户群也是甚大的,所以我们这 ...
- Django中用户权限模块
Django中用户权限模块 1 auth模块 auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理. auth可以和admin模块配合使用, 快速建立网站的管理系 ...
- 030 SSM综合练习06--数据后台管理系统--SSM权限操作及Spring Security入门
1.权限操作涉及的三张表 (1)用户表信息描述users sql语句: CREATE TABLE users ( id ) DEFAULT SYS_GUID () PRIMARY KEY, email ...
- 权限控制框架Spring Security 和Shiro 的总结
关于权限控制,一开始感觉比较难,后来先是接触了Spring Security 学起来也比较吃力,再是学习了Shiro,感觉简单很多. 总体来说这些框架,主要做了两个事情 Authentication: ...
- Spring安全权限管理(Spring Security)
1.spring Security简要介绍 Spring Security以前叫做acegi,是后来才成为Spring的一个子项目,也是目前最为流行的一个安全权限管理框架,它与Spring紧密结合在一 ...
- 【权限管理系统】Spring security(三)---认证过程(原理解析,demo)
在前面两节Spring security (一)架构框架-Component.Service.Filter分析和Spring Security(二)--WebSecurityConfigurer配 ...
- 【权限管理】Spring Security 执行流程
转自:https://blog.csdn.net/weixin_37689658/article/details/92752890 1.基本配置使用 (1)创建配置类 创建一个配置类SecurityC ...
- 用户权限模块之oauth2.0
主要是在springsecurity上面扩展即可,所以内容也是基于上一个, sql: CREATE TABLE `auth_access_token` ( `id` int(11) NOT NULL ...
- 给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 ...
随机推荐
- 视差滚动特效图片滑块-Sequence.js
效果演示 插件下载
- Net分布式系统之五:微服务架构
因工作较忙,抽时间将框架遇到的问题和框架升级设计进行记录. 一.背景&问题 之前框架是一个基于SOA思想设计的分布式框架.各应用通过服务方式提供使用,服务之间通信是RPC方式调用,具体实现基于 ...
- Cocos2d-x 3.2 环境搭建
参考文章地址: 1.Cocos2d-x官方安装说明文档:http://cn.cocos2d-x.org/tutorial/show?id=781 2.CSDN博客:http://blog.csdn.n ...
- hadoop单机环境搭建
[在此处输入文章标题] Hadoop单机搭建 1. 工具准备 1) Hadoop Linux安装包 2) VMware虚拟机 3) Java Linux安装包 4) Window 电脑一台 2. 开始 ...
- TP5学习基础二:目录结构、URL路由、数据操作
一.安装1.使用git或者composer(composer update)进行实时更新,区别在于git不会清空核心框架目录而composer会清空.2.使用官网打包好的TP压缩包(解压即可用)-&g ...
- Docker - 在Ubuntu16.04中安装Docker CE
Get Docker for Ubuntu Check system version root@Ubuntu16:~# uname -a Linux Ubuntu16 4.8.0-36-generic ...
- redis中的事务
首先明白在java中线程和进程的区别: 1.什么是多线程? 是指一个应用程序同时执行多个任务,一般来说一个任务就是一个线程 ,而一个应用程序有一个以上的线程我们称之为多线程. 2.什么是进程? 进程是 ...
- WinRAR5.01注册码附注册机
把下面的注册码复制到"记事本"中,另存为"rarreg.key"文件,放到WinRAR安装目录即完成注册.RAR registration datakjcy8U ...
- JavaScript开发中几个常用知识点总结
最近在做项目的时候自己写了一些JavaScipt代码,于是自己又进行简单的查阅资料整理了一下,发现了如下几个比较有用的知识点: 1.三种声明函数的方式 2.jQuery $(document).rea ...
- wifi驱动总结(2)
1.dhd_module_init(驱动模块初始化函数) → dhd_wifi_platform_register_drv(查找设备,注册驱动) → 1) wifi_ctrlfunc_register ...