栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security进行权限控制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security进行权限控制

一、SpringSecurity介绍
  • 简介
    SpringSecurity是一个专注于java应用程序提供身份认证和授权的框架,它的强大之处在于它可以轻松扩展以满足自定义的需求
  • 特征
    – 对身份的认证和授权提供全面的、可扩展的支持。
    – 防止各种攻击,如会话固定攻击、点击劫持、csrf攻击等。
    – 支持与Servlet API,Spring MVC等web技术支持
  • SpringSecurity底层是通过11钟过滤器进行实现,属于JavaEE层面

    SpringSecurity底层详解网站推荐:http://www.spring4all.com/article/428
二、利用SpringSecurity进行权限控制

引入依赖


    org.springframework.boot
    spring-boot-starter-security

编写config类

对未登录,权限不足以及退出时进行过滤

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant {
    //忽略对静态资源的拦截
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //授权
        http.authorizeRequests()
                //需要授权的请求
                .antMatchers(
                        "/user/setting",
                        "/user/upload",
                        "/discuss/add",
                        "/comment/add/**",
                        "/letter/**",
                        "/notice/**",
                        "/like",
                        "/follow",
                        "/followee/**",
                        "/follower/**"
                )
                //上述请求需要的身份
                .hasAnyAuthority(
                        AUTHORITY_USER,
                        AUTHORITY_ADMIN,
                        AUTHORITY_MODERATOR
                )
                //拥有身份时允许的行为
                .anyRequest().permitAll();

        //权限不够时的操作
        http.exceptionHandling()
                //没有登陆
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                        //当请求头是x-requested-with=XMLHttpRequest时说明是异步请求,返回JSON字符串
                        String xRequestedWith = request.getHeader("x-requested-with");
                        //if (xRequestedWith.equals("XMLHttpRequest")) {会报空指针异常
                        if ("XMLHttpRequest".equals(xRequestedWith)) {
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            writer.write(CommunityUtil.getJSONString(403, "您还没有登录!"));
                        } else {
                            response.sendRedirect(request.getContextPath() + "/login");
                        }
                    }
                })
                //权限不足
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                        //当请求头是x-requested-with=XMLHttpRequest时说明是异步请求,返回JSON字符串
                        String xRequestedWith = request.getHeader("x-requested-with");
                        //if (xRequestedWith.equals("XMLHttpRequest")) {会报空指针异常
                        if ("XMLHttpRequest".equals(xRequestedWith)) {
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            writer.write(CommunityUtil.getJSONString(403, "您没有访问的权限!"));
                        } else {
                            response.sendRedirect(request.getContextPath() + "/denied");
                        }
                    }
                });
        //security底层默认会拦截/logout请求,进行退出处理,覆盖他的逻辑,才能执行我们自己的推出代码
        http.logout().logoutUrl("/securitylogout");//写一个没有的请求欺骗springSecurity
    }
}

if (xRequestedWith.equals(“XMLHttpRequest”)) 会报空指针异常,因为xRequestedWith可能为null
改为if (“XMLHttpRequest”.equals(xRequestedWith)) 防止此错误

编写userService类实现获取用户权限的方法

@Override
public Collection getAuthorities(int userId) {
    //获得当前登录用户
    User user = this.findUserById(userId);
    //将用户权限装入List
    List list = new ArrayList<>();
    list.add(new GrantedAuthority() {
        @Override
        public String getAuthority() {
            switch (user.getType()){
                case 1:
                    return AUTHORITY_ADMIN;
                case 2:
                    return AUTHORITY_MODERATOR;
                default:
                    return AUTHORITY_USER;
            }
        }
    });
    return list;
}

将认证信息写入过滤器

写入过滤器的preHandle方法,在每一次请求前都调用

//构建用户认证的结果,并存入SecurityContext,以便于security进行授权
Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), userService.getAuthorities());
SecurityContextHolder.setContext(new SecurityContextImpl(authentication));

并在请求结束时的afterCompletion方法中清楚认证

SecurityContextHolder.clearContext();

防止csrf攻击

  • csrf攻击:
    在用户提交表单时,不法网站可能窃取用户提交的信息进行提交从而造成安全问题
  • 解决办法
    springsecurity中在用户同步提交表单时设置了一个隐藏的token,不但会对用户提交的信息进行核实,还会对token进行核实,在异步提交的时候则需要自行在前端加入token提交
  • 异步请求时徐手动添加token的提交



//发送ajax请求前,将csrf令牌设置到请求的消息头中
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function (e, xhr, options) {
	xhr.setRequestHeader(header, token)
})


添加成功

三、整合前端模板

引入依赖


    org.thymeleaf.extras
    thymeleaf-extras-springsecurity5

前端引入


模块设置


满足moderator权限时才显示

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/825405.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号