SpringBoot+SpringSecurity整合(四)自定义Access

SpringSecurity角色和权限授权

在登录成功之后,会有少部分资源不会给没有权限的人进行开放,比如说爱奇艺会员,只有会员才能看会员专享的电影,SpringBoot+SpringSecurity整合(二)中将当前用户的角色和权限加入到了UserUserDetails中,这样就可以进行角色和权限的判断了

 @Override
   protected void configure(HttpSecurity http) throws Exception {
       // 表单登录
       http.formLogin()
               // 自定义表单接收参数
               .usernameParameter("username")
               .passwordParameter("password")
               // 设置登录页面
               .loginPage("/login.html")
               // 登录的请求必须和表单登录的url一致
               .loginProcessingUrl("/login")
               // 登录成功的页面(这里不能直接写页面要通过POST请求跳到页面)
               .defaultSuccessUrl("/toMain")
               // 登录成功的控制器
               //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
               // 登录失败的页面(这里不能直接写页面要通过POST请求跳到页面)
               .failureForwardUrl("/toError");
               // 登录失败的控制器
               //.failureHandler(new MyAuthenticationFailureHandler("http://www.alibaba.com"));

       // 授权
       http.authorizeRequests()
               // 对登录页面、登录成功的页面,登录失败的请求不做授权访问
               .antMatchers("/login.html","/error.html").permitAll()
               // 通过正则表达式进行放行放行后缀为png的文件
               .regexMatchers(".+[.]png").permitAll()
               // 登录成功之后具有某一个角色才能访问该页面(字母严格区分大小写),此处不用添加ROLE_前缀,这里会自动添加上ROLE_前缀,
               // 在mySecurityUserDetails中添加角色时需要添加上ROLE_前缀
               .regexMatchers("/main1.html").hasRole("ADMIN")
               // 登录成功之后具有某一个权限才能访问该页面(字母严格区分大小写)
               .regexMatchers("/main1.html").hasAuthority("admin")
               // 其他所有的请求必须得经过授权,必须登录
                .anyRequest().authenticated();
               // 使用自定义的access进行权限控制
               

       // 关闭CSRF跨域
       http.csrf().disable();
   }

还可以使用hasAnyRole()hasAnyAuthority()进行角色和权限的判断,hasAnyRole()方法要放入多个角色只要具有其中一种就可以进行相关资源的访问,hasAnyAuthority()方法也可以放多个权限用逗号隔开,只要有其中一种权限就可以访问

在SpringSecurity没有权限的页面可以自己定制

通过重写AccessDeniedHandler 这个接口的handle方法,然后再SpringSecurity配置类中注入此类在configure(HttpSecurity http)方法中添加代码

 // 统一的403页面
       http.exceptionHandling()
               .accessDeniedHandler(myAccessDeniedHandler);
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        httpServletResponse.setHeader("Content-Type","application/json");
        httpServletResponse.setCharacterEncoding("utf-8");
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write("{\"status\":\"403\",\"msg\":\"没有权限访问,请联系管理员\"}");
        writer.flush();
        writer.close();
    }
}

没有权限访问时会出现当前页面

在这里插入图片描述

自定义Access

通过观察源码可以发现hasRole()hasAuthority()hasAnyRole()hasAnyAuthority(),这些方法在低层都是通过access方法去实现的,如果SpringSecurity内置的不满足需求可以通过以下方法去自定义Access编写一个MyAccessService 接口

public interface MyAccessService {

    public boolean myUri(HttpServletRequest request, Authentication authentication);
}

进行实现并加上@Service注解

@Service
public class MyAccessServiceImpl implements MyAccessService {
    @Override
    public boolean myUri(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if(principal instanceof UserDetails){
            UserDetails userDetails = (UserDetails) principal;
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
            boolean contains = authorities.contains(new SimpleGrantedAuthority(request.getRequestURI()));
            return contains;
        }

        return false;
    }
}

将以下代码加入到末尾将.anyRequest().authenticated()进行替换,这样其他的资源访问权限就不是登录之后就可以访问,变成了这个人要有request.getRequestURI()这个uri的权限就是要在当前用户的权限中加入request.getRequestURI()的值才能访问

// 自定义access
.anyRequest().access("@myAccessServiceImpl.myUri(request,authentication)");

跨栈请求伪造

介绍

CSRF(Cross-Site Request Forgery,跨站点伪造请求)是一种网络攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在未授权的情况下执行在权限保护之下的操作,具有很大的危害性。具体来讲,可以这样理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。

实现

在SpringSecurity中默认打开了_csrf的功能当前项目为了方便关闭了此功能,如果使用此功能就必须在访问时加入参数,默认的_csrf参数是一个token是有SpringSecurity自动生成的在页面访问时必须加入以下的代码才能被SpringSecurity识别

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />

注释掉这一行代码就打开csrf的功能

// 关闭CSRF跨域
// http.csrf().disable();
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦片王子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值