zoukankan      html  css  js  c++  java
  • Spring Security -- 权限控制(转载)

    Spring Security权限控制可以配合授权注解使用,Spring Security提供了三种不同的安全注解:

    • Spring Security自带的@Secured注解;
    • JSR-250的@DenyAll、@RolesAllowed、@PermitAll注解;
    • 表达式驱动的注解,包括@PreAuthorize、@PostAuthorize、@PreFilter和 @PostFilter;

    一、权限控制注解

    1、@Secured注解

    在方法上指定安全性要求,只有对应角色的用户才可以调用这些方法:

    import org.springframework.security.access.annotation.Secured;
     
     
    public interface UserService {
     
        List<User> findAllUsers();
     
        @Secured("ROLE_ADMIN")
        void updateUser(User user);
     
        @Secured({ "ROLE_DBA", "ROLE_ADMIN" })
        void deleteUser();
        
    }

    权限不足时,方法抛出Access Denied异常。@Secured注解会使用一个String数组作为参数。每个String值是一个权限,调用这个方法至少需要具备其中的一个权限。

    2、@RolesAllowed

    • @DenyAll拒绝所有访问;
    • @RolesAllowed注解和@Secured注解在各个方面基本上都是一致的,@RolesAllowed({"ROLE_USER","ROLE_ADMIN"})该方法只要具有“ROLE_USER","ROLE_ADMIN"任意一种权限就可以访问;
    • @PermitAll允许所有访问;

    3、SpEL注解

    要开启表达式驱动的注解,只需要在Spring Security配置文件中添加如下注解:

    @EnableGlobalMethodSecurity(prePostEnabled = true)

    (1)、@PreAuthorize

    该注解用于方法前验证权限,比如限制非VIP用户提交blog的note字段字数不得超过1000字:

    @PreAuthorize("hasRole('ROLE_ADMIN') and #form.note.length() <= 1000 or hasRole('ROLE_VIP')")
    public void writeBlog(Form form){
        ...
    }

    表达式中的#form部分直接引用了方法中的同名参数。这使得Spring Security能够检查传入方法的参数,并将这些参数用于认证决策的制定。

    (2)、@PostAuthorize

    方法后调用权限验证,比如校验方法返回值:

    @PreAuthorize("hasRole(ROLE_USER)")
    @PostAuthorize("returnObject.user.userName == principal.username")
    public User getUserById(long id){
        ...        
    }

    Spring Security在SpEL中提供了名为returnObject 的变量。在这里方法返回一个User对象,所以这个表达式可以直接访问user对象中的userName属性。

    二、权限控制案例

    1、@PreAuthorize注解使用案例

    接着上一节,要开启这些注解,只需要在Spring Security配置文件中添加如下注解:

    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
       ...  
    }

    在CustomUserDetailsService中,我们给当前登录用户授予了”admin”的权限,我们将这块代码改造一下:当登录用户为admin的时候,其拥有”admin”权限,其它用户则只有”test”权限:

    @Service
    public class CustomUserDetailsService implements UserDetailsService {
        /**
         * 点击登录时会调用该函数、并传入登录名  根据用户名查询数据库获取用户信息
         * @param username:登录用户名
         * @return: 返回用户信息
         * @throws UsernameNotFoundException
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //模拟一个用户 替代数据库获取逻辑
            User user = new User();
            user.setUsername(username);
            user.setPassword("123456");
            // 输出加密后的密码
            System.out.println(user.getPassword());
    
            List<GrantedAuthority> authorities = new ArrayList<>();
            if (StringUtils.equalsIgnoreCase("admin", username)) {
                authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
            } else {
                authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("test");
            }
    
            return new org.springframework.security.core.userdetails.User(user.getUsername(),
                    user.getPassword(),
                    user.isEnabled(),
                    user.isAccountNonExpired(),
                    user.isCredentialsNonExpired(),
                    user.isAccountNonLocked(),
                    authorities);
        }
    }

    在类TestController添加一个方法,并且使用权限注解标明只有拥有“admin”权限的人才能访问:

    @GetMapping("/auth/admin")
    @PreAuthorize("hasAuthority('admin')")
    public String authenticationTest() {
        return "您拥有admin权限,可以查看";
    }

    启动系统,访问http://127.0.0.1:8080/index,使用admin账号登录:

    访问http://127.0.0.1:8080/auth/admin

    可看到,admin可以访问该资源。

    使用zy账号登录:

     

    可以看到,zy没有权限访问,进入了403页面。

    2、自定义权限不足处理逻辑

    我们可以自定义权限不足处理逻辑。在包com.goldwind.handler下新增一个类CustomAuthenticationAccessDeniedHandler,实现AccessDeniedHandler接口:

    package com.goldwind.handler;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.security.web.access.AccessDeniedHandler;
    import org.springframework.stereotype.Service;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @Author: zy
     * @Description: 自定义权限不足处理逻辑
     * @Date: 2020/2/16
     */
    @Service
    public class CustomAuthenticationAccessDeniedHandler implements AccessDeniedHandler {
        @Override
        public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
            httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            httpServletResponse.setContentType("application/json;charset=utf-8");
            httpServletResponse.getWriter().write("很抱歉,您没有该访问权限");
        }
    }

    然后进行Spring Security配置: @Autowired private AccessDeniedHandler accessDeniedHandler;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.exceptionHandling()
                    .accessDeniedHandler(accessDeniedHandler)
                    .and()
                    ...
        }

    重启系统,再次使用zy账号访问/auth/admin:

    参考文章:

    [1] Spring Security保护方法(转载)

    [2] Spring Security权限控制(转载)

  • 相关阅读:
    error C2146: 语法错误 : 缺少“;”
    字符串大小写格式化
    Click Button关键字——模拟单击页面中的按钮
    Get List Items关键字——获取页面中一个下拉列表中的所有下拉框选项
    Get Title关键字——获取浏览器网页的title
    Click Link关键字——模拟单击一个链接
    Get Text关键字——用来获取文本内容
    Input Text关键字——模拟向一个输入框中输入文字内容
    Open Browser、Close Browser关键字——打开和关闭浏览器
    Go Back关键字、Go To关键字——浏览器的后退、前进操作
  • 原文地址:https://www.cnblogs.com/zyly/p/12316920.html
Copyright © 2011-2022 走看看