• 【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

  • 相关阅读:
    夺命雷公狗—玩转SEO---64---高质量链接打造
    夺命雷公狗—玩转SEO---63---页面相似度算法原理
    夺命雷公狗—玩转SEO---62---TF-IDF核心算法与运用
    夺命雷公狗—玩转SEO---61---全站title与description深层次玩法,门户站和流量站
    夺命雷公狗—玩转SEO---60---全站title与description深层次玩法,企业站内容页
    夺命雷公狗—玩转SEO---59---全站title与description深层次玩法,企业站列表页
    夺命雷公狗—玩转SEO---58---全站title与description深层次玩法,企业站首页篇
    夺命雷公狗—玩转SEO---57---DEDE副标题大爆发
    夺命雷公狗—玩转SEO---56---query需求分析与搜索意图研究
    夺命雷公狗—玩转SEO---55---页面去重原理
  • 原文地址:https://www.cnblogs.com/mindzone/p/13744769.html
Copyright © 2020-2023  润新知