权限表达式
通过源码分析可知,最终的配置都会转成ExpressionUrlAuthorizationConfigurer.AuthorizedUrl并进行投票决定。
常见表达式如下:
如何写联合表达式呢?就是既满足A条件,也满足B条件
.antMatchers("xx").access("hasRole('ROLE_USER') and hasRole('ROLE_SUPER')")
这个都是spring自己的权限表达式,那么我们是否可以自定义实现自己的权限规则呢?可以的!这个我们下一章再看怎么实现。
权限业务配置分离
如何将权限模块配置和业务模块配置想分离呢?因为权限模块并不清楚业务模块的权限拦截规则。
实现思路如下:
- 提供AuthorizeConfigProvider接口,提供权限设置
- 权限模块的通用配置实现该接口,然后进行配置,业务模块按需也实现该接口进行配置
- 最后使用 AuthorizeConfigManager类来管理所有的AuthorizeConfigProvider实现
- 拿到所有的配置后,进行统一设置
代码实现如下:
权限控制接口及实现
-
package com.rui.tiger.auth.core.authorize;
-
-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
-
/**
-
* 自定义权限控制接口
-
* @author CaiRui
-
* @date 2019-05-06 12:02
-
*/
-
public
interface AuthorizeConfigProvider {
-
-
/**
-
* @param config
-
* @return 返回的boolean表示配置中是否有针对anyRequest的配置。在整个授权配置中,
-
* 应该有且仅有一个针对anyRequest的配置,如果所有的实现都没有针对anyRequest的配置,
-
* 系统会自动增加一个anyRequest().authenticated()的配置。如果有多个针对anyRequest
-
* 的配置,则会抛出异常。
-
*/
-
boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
-
}
通用权限设置
-
package com.rui.tiger.auth.core.authorize;
-
-
import com.rui.tiger.auth.core.properties.SecurityConstants;
-
import com.rui.tiger.auth.core.properties.SecurityProperties;
-
import lombok.extern.slf4j.Slf4j;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.core.annotation.Order;
-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
import org.springframework.stereotype.Component;
-
-
/**
-
* 通用权限接口配置管理
-
* @author CaiRui
-
* @date 2019-05-06 12:08
-
*/
-
@Component
-
@Slf4j
-
@Order(Integer.MIN_VALUE)
-
public
class CommonAuthorizeConfigProvider implements AuthorizeConfigProvider {
-
-
@Autowired
-
private SecurityProperties securityProperties;
-
-
@Override
-
public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
-
-
config.antMatchers(
-
SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
//权限认证
-
SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
//手机
-
SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_OPENID,
//openId
-
securityProperties.getBrowser().getLoginPage(),
//登录页面
-
SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+
"/*",
// /captcha/* 验证码放行
-
securityProperties.getBrowser().getSignupUrl(),
-
securityProperties.getBrowser().getLoginOut(),
-
securityProperties.getBrowser().getSession().getInvalidSessionUrl()
-
).permitAll();
//放行
-
-
return
false;
-
}
-
}
业务模块权限设置
-
package com.rui.tiger.auth.demo.security;
-
-
import com.rui.tiger.auth.core.authorize.AuthorizeConfigProvider;
-
import org.springframework.core.annotation.Order;
-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
import org.springframework.stereotype.Component;
-
-
/**
-
* 业务模块权限配置实现
-
* @author CaiRui
-
* @date 2019-05-06 12:16
-
*/
-
@Component
-
@Order(Integer.MAX_VALUE)
-
public
class DemoAuthorizeConfigProvider implements AuthorizeConfigProvider {
-
-
@Override
-
public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
-
config.antMatchers(
-
"/user/regist",
// 注册请求
-
"/error",
-
"/connect/*",
-
"/auth/*",
-
"/signin",
-
"/social/signUp",
// app注册跳转服务
-
"/swagger-ui.html",
-
"/swagger-ui.html/**",
-
"/webjars/**",
-
"/swagger-resources/**",
-
"/v2/**"
-
).permitAll();
-
-
/*
-
利用@Order注解实现CommonAuthorizeConfigProvider中的放行路径不需要自定义权限验证
-
*/
-
config.anyRequest()
-
.access(
"@rbacService.hasPermission(request,authentication)");
-
-
return
true;
-
}
-
}
权限接口管理器及实现
-
package com.rui.tiger.auth.core.authorize;
-
-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
-
/**
-
* 权限控制接口持有管理者
-
* @author CaiRui
-
* @date 2019-05-06 12:05
-
*/
-
public
interface AuthorizeConfigManager {
-
-
void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
-
}
-
package com.rui.tiger.auth.core.authorize;
-
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
import org.springframework.stereotype.Component;
-
-
import java.util.List;
-
import java.util.Set;
-
-
/**
-
* @author CaiRui
-
* @date 2019-05-06 12:12
-
*/
-
@Component
-
public
class DefaultAuthorizeConfigManager implements AuthorizeConfigManager {
-
-
//有依赖顺序 通过@Order控制 不用set
-
@Autowired
-
private List<AuthorizeConfigProvider> providers;
-
-
@Override
-
public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
-
-
boolean existAnyRequestConfig =
false;
-
String existAnyRequestConfigName =
null;
-
-
for (AuthorizeConfigProvider authorizeConfigProvider : providers) {
-
boolean currentIsAnyRequestConfig = authorizeConfigProvider.config(config);
-
if (existAnyRequestConfig && currentIsAnyRequestConfig) {
-
throw
new RuntimeException(
"重复的anyRequest配置:" + existAnyRequestConfigName +
","
-
+ authorizeConfigProvider.getClass().getSimpleName());
-
}
else
if (currentIsAnyRequestConfig) {
-
existAnyRequestConfig =
true;
-
existAnyRequestConfigName = authorizeConfigProvider.getClass().getSimpleName();
-
}
-
}
-
-
if(!existAnyRequestConfig){
-
config.anyRequest().authenticated();
-
}
-
}
-
}
浏览器模块配置进行调整(app模块同理),就是将原来的配置抽离出去。
-
@Override
-
protected void configure(HttpSecurity http) throws Exception {
-
/**
-
* 表单密码配置
-
*/
-
applyPasswordAuthenticationConfig(http);
-
http
-
.apply(captchaSecurityConfig)
-
.and()
-
.apply(smsAuthenticationSecurityConfig)
-
.and()
-
.apply(tigerSpringSocialConfigurer)
-
.and()
-
.rememberMe()
-
.tokenRepository(persistentTokenRepository())
-
.tokenValiditySeconds(securityProperties.getBrowser().getRemberMeSeconds())
-
.userDetailsService(userDetailsService)
-
.and()
-
.sessionManagement()
-
.invalidSessionStrategy(invalidSessionStrategy)
//session失效策略
-
.maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
//最大session并发数
-
.maxSessionsPreventsLogin(securityProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())
//true达到并发数后阻止登录,false 踢掉之前的登录
-
.expiredSessionStrategy(sessionInformationExpiredStrategy)
//并发策略
-
.and()
-
.and()
-
.logout()
-
.logoutUrl(
"/loginOut")
//默认logout
-
//.logoutSuccessUrl("") url和Handler只能配置一个
-
.logoutSuccessHandler(tigerLogoutSuccessHandler)
-
.deleteCookies(
"JSESSIONID")
//清楚cook键值
-
.and()
-
.csrf().disable();
-
//配置管理
-
authorizeConfigManager.config(http.authorizeRequests());
-
-
}
文章转载至:https://blog.csdn.net/ahcr1026212/article/details/89875404