Usually we control permissions by @PreAuthorize("hasRole('ROLE_USER')) annotation, and configuring permission requirements in HttpSecurity. Here, we control access rights based on the requested URI, and we can use annotations to control access rights.
Create a new resource project to allocate resources and services. First, we customize a privilege authentication MySecurity Access Decision Manager to inherit the Access Decision Manager interface and override the decision method. And copy the remaining two methods of default permission validation for AbstractAccessDecision Manager (the focus of annotation control). The user's privileges have been customized in the authentication server.
/** * @Description Customize permission authentication, get url to determine whether permission exists * @Author wwz * @Date 2019/08/01 * @Param * @Return */ @Component public class MySecurityAccessDecisionManager implements AccessDecisionManager { private List<AccessDecisionVoter<? extends Object>> decisionVoters; @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { String requestUrl = ((FilterInvocation) object).getRequest().getMethod() + ((FilterInvocation) object).getRequest().getRequestURI(); // System.out.println("requestUrl>>" + requestUrl); // Permissions of the current user Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); // System.out.println("authorities=" + authorities); for (GrantedAuthority grantedAuthority : authorities) { if (grantedAuthority.getAuthority().equals(requestUrl)) { return; } if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) { return; } } throw new AccessDeniedException("No access rights"); } /** * Copy the default method to make @PreAuthorize("hasRole('ROLE_ADMIN')) available */ @Override public boolean supports(ConfigAttribute attribute) { for (AccessDecisionVoter voter : this.decisionVoters) { if (voter.supports(attribute)) { return true; } } return false; } @Override public boolean supports(Class<?> clazz) { for (AccessDecisionVoter voter : this.decisionVoters) { if (!voter.supports(clazz)) { return false; } } return true; } }
Rewrite and inject in HTTP security of resource service configuration:
/** * @Description Resource authentication * @Author wwz * @Date 2019/08/01 * @Param * @Return */ @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true) // Enable Annotation Permission Configuration public class MySecurityResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private RedisConnectionFactory connectionFactory; @Bean public TokenStore tokenStore() { RedisTokenStore redis = new RedisTokenStore(connectionFactory); return redis; } @Resource private MyAccessDeniedHandler accessDeniedHandler; // No access to processor @Resource private MyTokenExceptionEntryPoint tokenExceptionEntryPoint; // token failure processor @Resource private MySecurityAccessDecisionManager accessDecisionManager; //Authority judgement @Override public void configure(HttpSecurity http) throws Exception { http .csrf().disable() .exceptionHandling().authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // In addition, if not set, then when accessing any protected resource through a browser, each time it is a different Session ID, and the history of each request is recorded in OAuth 2Authentication details. .and() .authorizeRequests().antMatchers("/actuator/health").permitAll().anyRequest().authenticated() // Http Security passes health checks and all other validation settings need to be set. anyRequest().authenticated() before entering the custom permission judgment. .and() .requestMatchers().antMatchers("/auth/**") // The. requestMatchers().antMatchers(...) OAuth2 settings protect resources and intercept them with /** .and() .authorizeRequests() .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { // Rewrite for permission judgment @Override public <O extends FilterSecurityInterceptor> O postProcess(O o) { o.setAccessDecisionManager(accessDecisionManager); // Authority judgement return o; } }) .and() .httpBasic(); http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.authenticationEntryPoint(tokenExceptionEntryPoint); // token failure processor resources.resourceId("manager"); // Setting the resource id to determine whether a resource with resource privileges does not exist will report Invalid token does not contain resource id (manager) } }
At the interruption point of MySecurity Access Decision Manager, it can be found that all requests go here to judge whether they have the right to access. According to the combination of privileges in the authentication server, matching uri requests with annotation privileges in the method can be used to judge whether they have the right to access. The principle is to go beyond the limit, otherwise they have no right.