pom.xml
- "1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
- <parent>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-parentartifactId>
- <version>2.7.3version>
- <relativePath/>
- parent>
- <groupId>com.examplegroupId>
- <artifactId>demoartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>demoname>
- <description>Demo project for Spring Bootdescription>
- <properties>
- <java.version>1.8java.version>
- properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-securityartifactId>
- dependency>
-
- ...
- dependencies>
-
- ...
-
- project>
FilterInvocationSecurityMetadataSource:获取数据源
- public interface FilterInvocationSecurityMetadataSource extends SecurityMetadataSource {
- }
SecurityMetadataSource
- public interface SecurityMetadataSource extends AopInfrastructureBean {
- Collection
getAttributes(Object object) throws IllegalArgumentException; - //获取object对应的权限
-
- Collection
getAllConfigAttributes(); -
- boolean supports(Class> clazz);
- }
ConfigAttribute:权限属性
- public interface ConfigAttribute extends Serializable {
- String getAttribute();
- }
SecurityConfig:attrib可用来设置权限值(admin、user等)
- public class SecurityConfig implements ConfigAttribute {
- private final String attrib;
-
- public SecurityConfig(String config) {
- Assert.hasText(config, "You must provide a configuration attribute");
- this.attrib = config;
- }
-
- public boolean equals(Object obj) {
- if (obj instanceof ConfigAttribute) {
- ConfigAttribute attr = (ConfigAttribute)obj;
- return this.attrib.equals(attr.getAttribute());
- } else {
- return false;
- }
- }
-
- public String getAttribute() {
- return this.attrib;
- }
-
- public int hashCode() {
- return this.attrib.hashCode();
- }
-
- public String toString() {
- return this.attrib;
- }
-
- public static List
createListFromCommaDelimitedString(String access) { - return createList(StringUtils.commaDelimitedListToStringArray(access));
- }
-
- public static List
createList(String... attributeNames) { - Assert.notNull(attributeNames, "You must supply an array of attribute names");
- List
attributes = new ArrayList(attributeNames.length); - String[] var2 = attributeNames;
- int var3 = attributeNames.length;
-
- for(int var4 = 0; var4 < var3; ++var4) {
- String attribute = var2[var4];
- attributes.add(new SecurityConfig(attribute.trim()));
- }
-
- return attributes;
- }
- }
AbstractSecurityInterceptor
- public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware {
- protected final Log logger = LogFactory.getLog(this.getClass());
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- private ApplicationEventPublisher eventPublisher;
- private AccessDecisionManager accessDecisionManager;
- private AfterInvocationManager afterInvocationManager;
- private AuthenticationManager authenticationManager = new AbstractSecurityInterceptor.NoOpAuthenticationManager();
- private RunAsManager runAsManager = new NullRunAsManager();
- private boolean alwaysReauthenticate = false;
- private boolean rejectPublicInvocations = false;
- private boolean validateConfigAttributes = true;
- private boolean publishAuthorizationSuccess = false;
-
- public AbstractSecurityInterceptor() {
- }
-
-
- public void afterPropertiesSet() {
- public void setRunAsManager(RunAsManager runAsManager) {
- public void setMessageSource(MessageSource messageSource) {
- public void setAlwaysReauthenticate(boolean alwaysReauthenticate) {
- public void setAuthenticationManager(AuthenticationManager newManager) {
- public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
- public void setValidateConfigAttributes(boolean validateConfigAttributes) {
- public void setPublishAuthorizationSuccess(boolean publishAuthorizationSuccess) {
- public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
- public void setAfterInvocationManager(AfterInvocationManager afterInvocationManager) {
- public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
-
-
- public boolean isAlwaysReauthenticate() {
- public boolean isRejectPublicInvocations() {
- public boolean isValidateConfigAttributes() {
-
- public AccessDecisionManager getAccessDecisionManager() {
- public AfterInvocationManager getAfterInvocationManager() {
- public AuthenticationManager getAuthenticationManager() {
- public RunAsManager getRunAsManager() {
-
-
- public abstract Class> getSecureObjectClass();
- public abstract SecurityMetadataSource obtainSecurityMetadataSource();
-
- protected void finallyInvocation(InterceptorStatusToken token) {
- protected InterceptorStatusToken beforeInvocation(Object object) {
- protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
-
-
- private Authentication authenticateIfRequired() {
- private void publishEvent(ApplicationEvent event) {
- private void validateAttributeDefs(Collection
attributeDefs) { - private void attemptAuthorization(Object object, Collection
attributes, Authentication authenticated) { - private void credentialsNotFound(String reason, Object secureObject, Collection
configAttribs) { -
-
- *********
- 静态内部类:NoOpAuthenticationManager
-
- private static class NoOpAuthenticationManager implements AuthenticationManager {
- private NoOpAuthenticationManager() {
- }
-
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- throw new AuthenticationServiceException("Cannot authenticate " + authentication);
- }
- }
- }
FilterSecurityInterceptor
- public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
- private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
- private FilterInvocationSecurityMetadataSource securityMetadataSource;
- private boolean observeOncePerRequest = true;
-
- public FilterSecurityInterceptor() {
- }
-
- public void init(FilterConfig arg0) {
- }
-
- public void destroy() {
- }
-
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- this.invoke(new FilterInvocation(request, response, chain));
- }
-
- public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
- this.securityMetadataSource = newSource;
- }
-
- public Class> getSecureObjectClass() {
- return FilterInvocation.class;
- }
-
- public void invoke(FilterInvocation filterInvocation) throws IOException, ServletException {
- if (this.isApplied(filterInvocation) && this.observeOncePerRequest) {
- filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
- } else {
- if (filterInvocation.getRequest() != null && this.observeOncePerRequest) {
- filterInvocation.getRequest().setAttribute("__spring_security_filterSecurityInterceptor_filterApplied", Boolean.TRUE);
- }
-
- InterceptorStatusToken token = super.beforeInvocation(filterInvocation);
-
- try {
- filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
- } finally {
- super.finallyInvocation(token);
- }
-
- super.afterInvocation(token, (Object)null);
- }
- }
-
- private boolean isApplied(FilterInvocation filterInvocation) {
- return filterInvocation.getRequest() != null && filterInvocation.getRequest().getAttribute("__spring_security_filterSecurityInterceptor_filterApplied") != null;
- }
-
- public boolean isObserveOncePerRequest() {
- return this.observeOncePerRequest;
- }
-
- public void setObserveOncePerRequest(boolean observeOncePerRequest) {
- this.observeOncePerRequest = observeOncePerRequest;
- }
- }
AccessDecisionManager
- public interface AccessDecisionManager {
- void decide(Authentication authentication, Object object, Collection
configAttributes) throws AccessDeniedException, InsufficientAuthenticationException; -
- boolean supports(ConfigAttribute attribute);
-
- boolean supports(Class> clazz);
- }
AbstractAccessDecisionManager
- public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean, MessageSourceAware {
- protected final Log logger = LogFactory.getLog(this.getClass());
- private List
> decisionVoters; - protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- private boolean allowIfAllAbstainDecisions = false;
-
-
- public boolean supports(ConfigAttribute attribute) {
- Iterator var2 = this.decisionVoters.iterator();
-
- AccessDecisionVoter voter;
- do {
- if (!var2.hasNext()) {
- return false;
- }
-
- voter = (AccessDecisionVoter)var2.next();
- } while(!voter.supports(attribute));
-
- return true;
- }
-
- public boolean supports(Class> clazz) {
- Iterator var2 = this.decisionVoters.iterator();
-
- AccessDecisionVoter voter;
- do {
- if (!var2.hasNext()) {
- return true;
- }
-
- voter = (AccessDecisionVoter)var2.next();
- } while(voter.supports(clazz));
-
- return false;
- }
-
-
- public void setMessageSource(MessageSource messageSource) {
- public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) {
-
- public List
> getDecisionVoters() { - public boolean isAllowIfAllAbstainDecisions() {
-
- public String toString() {
- public void afterPropertiesSet() {
-
- protected final void checkAllowIfAllAbstainDecisions() {
- protected AbstractAccessDecisionManager(List
> decisionVoters) {
AffirmativedBased
- public class AffirmativeBased extends AbstractAccessDecisionManager {
- public AffirmativeBased(List
> decisionVoters) { - super(decisionVoters);
- }
-
- public void decide(Authentication authentication, Object object, Collection
configAttributes) throws AccessDeniedException { - int deny = 0;
- Iterator var5 = this.getDecisionVoters().iterator();
-
- while(var5.hasNext()) {
- AccessDecisionVoter voter = (AccessDecisionVoter)var5.next();
- int result = voter.vote(authentication, object, configAttributes);
- switch(result) {
- case -1:
- ++deny;
- break;
- case 1:
- return;
- }
- }
-
- if (deny > 0) {
- throw new AccessDeniedException(this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
- } else {
- this.checkAllowIfAllAbstainDecisions();
- }
- }
- }
AccessDecisionVoter
- public interface AccessDecisionVoter
{ - int ACCESS_GRANTED = 1;
- int ACCESS_ABSTAIN = 0;
- int ACCESS_DENIED = -1;
-
- boolean supports(ConfigAttribute attribute);
-
- boolean supports(Class> clazz);
-
- int vote(Authentication authentication, S object, Collection
attributes) ; - }
RoleVoter:根据权限判断是否让请求通过
- public class RoleVoter implements AccessDecisionVoter
- private String rolePrefix = "ROLE_";
-
- public RoleVoter() {
- }
-
- public String getRolePrefix() {
- return this.rolePrefix;
- }
-
- public void setRolePrefix(String rolePrefix) {
- this.rolePrefix = rolePrefix;
- }
-
- public boolean supports(ConfigAttribute attribute) {
- return attribute.getAttribute() != null && attribute.getAttribute().startsWith(this.getRolePrefix());
- }
-
- public boolean supports(Class> clazz) {
- return true;
- }
-
- public int vote(Authentication authentication, Object object, Collection
attributes) { - if (authentication == null) {
- return -1;
- } else {
- int result = 0;
- Collection extends GrantedAuthority> authorities = this.extractAuthorities(authentication);
- Iterator var6 = attributes.iterator();
-
- while(true) {
- ConfigAttribute attribute;
- do {
- if (!var6.hasNext()) {
- return result;
- }
-
- attribute = (ConfigAttribute)var6.next();
- } while(!this.supports(attribute));
-
- result = -1;
- Iterator var8 = authorities.iterator();
-
- while(var8.hasNext()) {
- GrantedAuthority authority = (GrantedAuthority)var8.next();
- if (attribute.getAttribute().equals(authority.getAuthority())) {
- return 1;
- }
- }
- }
- }
- }
-
- Collection extends GrantedAuthority> extractAuthorities(Authentication authentication) {
- return authentication.getAuthorities();
- }
- }
AuthorityDto
- @Data
- public class AuthorityDto {
-
- private String path;
- private List
authorities; - }
SecurityDataSourceUtil
- public class SecurityDataSourceUtil {
-
- public static Map
> requestAuthoritiesMap = new HashMap<>(); -
- public static void setAuthorities(String path, Collection
configAttributes) { - requestAuthoritiesMap.put(path, configAttributes);
- }
-
- public static Collection
getAuthorities(String path){ - return requestAuthoritiesMap.get(path);
- }
- }
CustomFilterSecurityMetadataSource
- @Component
- public class CustomFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
-
- @Override
- public boolean supports(Class> clazz) {
- return FilterInvocation.class.isAssignableFrom(clazz);
- }
-
- @Override
- public Collection
getAllConfigAttributes() { - Set
configAttributes = new HashSet<>(); - for (Collection
item : SecurityDataSourceUtil.requestAuthoritiesMap.values()){ - configAttributes.addAll(item);
- }
-
- return configAttributes;
- }
-
- @Override
- public Collection
getAttributes(Object object) throws IllegalArgumentException { - HttpServletRequest request = ((FilterInvocation)object).getRequest();
-
- for (Map.Entry
> entry: SecurityDataSourceUtil.requestAuthoritiesMap.entrySet()){ - if (new AntPathRequestMatcher(entry.getKey()).matches(request)) {
- return entry.getValue();
- }
- }
-
- return null;
- }
- }
CustomUrlInterceptor
- @Data
- @Component
- @EqualsAndHashCode(callSuper = true)
- public class CustomUrlInterceptor extends AbstractSecurityInterceptor implements Filter, InitializingBean {
-
- private static final String FILTER_APPLIED = "__spring_security_custom_filterSecurityInterceptor_filterApplied";
- private boolean observeOncePerRequest = true;
-
- @Resource
- private FilterInvocationSecurityMetadataSource securityMetadataSource;
-
-
- public CustomUrlInterceptor() {
- }
-
- @Override
- public void afterPropertiesSet() {
- List
> accessDecisionVoters = new ArrayList<>(); - accessDecisionVoters.add(new RoleVoter());
-
- AccessDecisionManager accessDecisionManager = new AffirmativeBased(accessDecisionVoters);
- this.setAccessDecisionManager(accessDecisionManager);
- }
-
- public void init(FilterConfig arg0) {
- }
-
- public void destroy() {
- }
-
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- this.invoke(new FilterInvocation(request, response, chain));
- }
-
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public Class> getSecureObjectClass() {
- return FilterInvocation.class;
- }
-
- public void invoke(FilterInvocation filterInvocation) throws IOException, ServletException {
- if (this.isApplied(filterInvocation) && this.observeOncePerRequest) {
- filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
- } else {
- if (filterInvocation.getRequest() != null && this.observeOncePerRequest) {
- filterInvocation.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
- }
-
- InterceptorStatusToken token = super.beforeInvocation(filterInvocation);
-
- try {
- filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
- } finally {
- super.finallyInvocation(token);
- }
-
- super.afterInvocation(token, null);
- }
- }
-
- private boolean isApplied(FilterInvocation filterInvocation) {
- return filterInvocation.getRequest() != null && filterInvocation.getRequest().getAttribute(FILTER_APPLIED) != null;
- }
-
- public boolean isObserveOncePerRequest() {
- return this.observeOncePerRequest;
- }
-
- public void setObserveOncePerRequest(boolean observeOncePerRequest) {
- this.observeOncePerRequest = observeOncePerRequest;
- }
- }
WebSecurity
- @Configuration
- public class WebSecurity {
-
- @Bean
- public PasswordEncoder initPasswordEncoder(){
- return new Pbkdf2PasswordEncoder();
- }
- }
WebSecurityConfig
- @Configuration
- @EnableWebSecurity
- public class WebSecurityConfig {
-
- @Resource
- private PasswordEncoder passwordEncoder;
-
- @Resource
- private CustomUrlInterceptor customUrlInterceptor;
-
- @Bean
- public SecurityFilterChain initSecurityFilterChain(HttpSecurity http) throws Exception{
- http.addFilterAfter(customUrlInterceptor, FilterSecurityInterceptor.class);
- http.csrf().disable();
-
- return http.formLogin().and().authorizeRequests()
- .antMatchers("/authority").permitAll()
- .antMatchers("/hello").hasRole("admin")
- .anyRequest().authenticated()
- .and().build();
- }
-
- @Bean
- public UserDetailsService initUserDetailsService(){
- UserDetails userDetails = User.withUsername("gtlx").password(passwordEncoder.encode("123456")).roles("admin").build();
-
- return new InMemoryUserDetailsManager(userDetails);
- }
- }
HelloController
- @RestController
- public class HelloController {
-
- @RequestMapping("/hello")
- public String hello(){
- return "hello";
- }
-
- @RequestMapping("/hello2")
- public String hello2(){
- return "hello2";
- }
- }
AuthorityController
- @RestController
- public class AuthorityController {
-
- @RequestMapping("/authority")
- public String authority(@RequestBody AuthorityDto authorityDto){
- List
configAttributes = new ArrayList<>(); - for (String s: authorityDto.getAuthorities()){
- SecurityConfig securityConfig = new SecurityConfig("ROLE_"+s);
- configAttributes.add(securityConfig);
- }
- SecurityDataSourceUtil.setAuthorities(authorityDto.getPath(), configAttributes);
-
- return "success";
- }
- }
localhost:8080/hello,输入密码
localhost:8080/hello2
localhost:8080/authority,路径/hello2添加权限认证
localhost:8080/hello2,当前用户没有user权限,禁止访问
localhost:8080/authority,修改路径权限为admin
localhost:8080/hello2,当前用户有admin权限,可正常访问