【Spring-Security】Re06 自定义Access & 注解权限分配

一、基于ACCESS方法处理的实现:

我们之前使用的任何放行规则的方法,本质上还是调用access方法执行的

这也意味之我们可以直接使用access方法去方向,只需要注入不同的字符串即可

自定义Access实现:

业务层自定义接口:

package cn.zeal4j.service;

import org.springframework.security.core.Authentication;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 28 20:17
 */
public interface CustomService {
    Boolean hasPermission(HttpServletRequest httpServletRequest, Authentication authentication);
}

实现类:

package cn.zeal4j.service;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 28 20:20
 */
public class CustomServiceImpl implements CustomService{
    @Override
    public Boolean hasPermission(HttpServletRequest httpServletRequest, Authentication authentication) {
        // 用户信息对象
        Object principal = authentication.getPrincipal();
        
        if (principal instanceof UserDetails) {
            
            UserDetails userDetails = (UserDetails) principal;

            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();

            return authorities.contains(new SimpleGrantedAuthority(httpServletRequest.getRequestURI()));
        }
        return false;
    }
}

Access配置:

package cn.zeal4j.configuration;

import cn.zeal4j.handler.CustomAccessDeniedHandler;
import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;

/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 27 21:55
 */
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
                // 登陆请求参数设置
                usernameParameter("username").
                passwordParameter("password").
                loginPage("/login.html"). // 设置登陆页面URL路径
                loginProcessingUrl("/login.action"). // 设置表单提交URL路径
                // successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
                successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
                // failureForwardUrl("/error.page");  // 设置认证失败跳转URL路径 POST请求
                failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了

        httpSecurity.authorizeRequests().
                regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式
                antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行
                antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
                antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
                antMatchers("/admin.page").hasAnyAuthority("admin").
                /*antMatchers("/vip-01.page").hasAnyAuthority("vip-01").*/
                antMatchers("/vip-01.page").hasRole("vip-01").
                antMatchers("/ip.page").hasIpAddress("192.168.43.180").
                // mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配
                // antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀
                anyRequest().authenticated(). // 其他请求均需要被授权访问
                anyRequest().access("@customServiceImpl.hasPermission(httpServletRequest, authentication)"); // 自定义Access配置

        // CSRF攻击拦截关闭
        httpSecurity.csrf().disable();

        httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler);

    }
}

这个授权逻辑只允许赋予了对应的接口地址和的才能访问,像默认访问的index页面就会报错

二、@Secured注解:

package org.springframework.security.access.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Secured {
    String[] value();
}

该注解可以标记的位置,方法和类上面

可以声名的值是一个字符串数组

官方的解释:

用于声名角色权限控制,判断访问此方法是否具备注解中的角色,参数值必须以ROLE_开头

具体使用:

二、@PreAuthorize & @PostAuthorize:

@PreAuthorize 用于在方法或者类之前先判断权限,参数和access方法相同

@PostAuthorize 恰恰相反,在方法和类执行之后判断 

使用这些注解需要在启动类中打上@EnableGlobalMethodSecurity

内部字符串会被读取到,和在配置类中设置是差不多的

当然和配置类不同的是,该注解允许方法注入大写的角色权限前缀,例如ROLE_vip-01

原文地址:https://www.cnblogs.com/mindzone/p/13744769.html