zoukankan      html  css  js  c++  java
  • 0-Security框架的搭建

    1、后台Springboot-Security安全框架

    在搭建后台管理框架的时候使用的是Security框架,该框架的执行过程是这样的。

    用户类创建

    首先要创建一个User类,该类要实现UserDetails接口,在该接口中要实现几个方法,最主要的方法是

        /**
         * 收集用户的角色信息,把角色信息放入到集合中
         * @return
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
    
            ArrayList<GrantedAuthority> authorities = new ArrayList<>();
            for (Role role : roles) {
                authorities.add(new SimpleGrantedAuthority(role.getName()));
            }
            return authorities;
        }

    该方法主要是收集用户的角色信息。

    Serivice中

    登录时候通过用户名去数据库中查询,如果该用户不存在则抛出一个UsernameNotFoundException,如果用户存在的话直接返回用户;

    1-方式是这样的,该方法主要是对用户的用户名和密码进行校验

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(hrSevice).passwordEncoder(new BCryptPasswordEncoder());
        }

    2-方式是这样的,该方法主要是放行相应的接口,但是不能放行login接口。如果login是登录的url的话。

        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("login_p","/static/**");
        }

    3-方式是这样的

    @Override
        protected void configure(HttpSecurity http) throws Exception {
          http.authorizeRequests()
                  .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                      @Override
                      public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                          o.setSecurityMetadataSource(urlFilterConfig);
                          o.setAccessDecisionManager(webAccessDecisionManager);
                          return o;
                      }
                  })
                  .and()
                  .formLogin().loginPage("/login_p").loginProcessingUrl("/login")
                  .usernameParameter("username").passwordParameter("password")
                  .successHandler(new AuthenticationSuccessHandler() {
                      @Override
                      public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                          resp.setContentType("application/json;charset=utf-8");
                          ObjectMapper om = new ObjectMapper();
                          PrintWriter out = resp.getWriter();
                          out.write( om.writeValueAsString(RespBean.ok("登录成功!", HrUtils.getCurrentHrInfo())));
                          out.flush();
                          out.close();
                      }
                  })
                  .failureHandler(new AuthenticationFailureHandler() {
                      @Override
                      public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
                          resp.setContentType("application/json;charset=utf-8");
                          ObjectMapper om = new ObjectMapper();
                          PrintWriter out = resp.getWriter();
                          out.write( om.writeValueAsString(RespBean.ok("登录失败!",null)));
                          out.flush();
                          out.close();
                      }
                  })
    
                  .permitAll()
                  .and()
                  .logout()
                  .logoutUrl("/logout")
                  .permitAll()
                  .and()
                  .csrf().disable().exceptionHandling().accessDeniedHandler(accessExceptionHandler);
        }

    这个带颜色的几个部分别是:

    1、所有的请求都学要授权,不然的话没法访问

    2、处理具体的授权请求

    3、配置用户登录时候的基本信息

    4、登录成功或失败的回调函数

    5、退出登录时候要处理的事情

    6、没有访问权限时候的异常处理

    4-处理所有浏览器提交的url

    @Component
    public class UrlFilterConfig implements FilterInvocationSecurityMetadataSource {
    
        @Autowired
        MenuService menuService;
    
        @Override
        public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
            String requestUrl = ((FilterInvocation) o).getRequestUrl(); //拦截所有的url
            AntPathMatcher antPathMatcher = new AntPathMatcher(); //匹配url使用的
    
            if (requestUrl.equals("/login_p")){  //如果url是以login_p开始的则不需要拦截,直接放行
                return null; //如果是登录页不需要认证
            }
    
            List<Menu> menus = menuService.getAllMenus(); //查询菜单表中所有的内容,并且把 菜单中的每一个项目都和角色对应上关系,注意查询出来的结果也是倒着排列的哦
    
            for (Menu menu : menus) {
                //如果请求的url是menu中存在的
                if (antPathMatcher.match(menu.getUrl(), requestUrl) && menu.getRoles().size()>0){  //如果请求的url在菜单中有并且菜单中的url也有相应的角色
                    List<Role> roles = menu.getRoles(); //取出该url所具有的角色
                    int size = roles.size();
                    String[] values = new String[size];
    
                    for (int i = 0; i < roles.size(); i++) { //收集该url所应该具有的角色
                      values[i] = roles.get(i).getName();
                    }
    
                    return  SecurityConfig.createList(values);  //返回该url应该所具有的角色给下一级
                }
            }
            //如果请求的url不是数据库中存在的
            return SecurityConfig.createList("ROLE_LOGIN"); //如果请求的url在菜单中没有,返回给一个ROLE_LOGIN信息给下一级
        }
    
        @Override
        public Collection<ConfigAttribute> getAllConfigAttributes() {
            return null;
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return SecurityConfig.class.isAssignableFrom(aClass);
        }
    }

    5-是真正处理权限的类

    @Component
    public class WebAccessDecisionManager implements AccessDecisionManager {
        @Override
        public void decide(Authentication auth, Object o, Collection<ConfigAttribute> cas) throws AccessDeniedException, InsufficientAuthenticationException {
    
            Iterator<ConfigAttribute> iterator = cas.iterator(); //迭代一下,为了能进行下一步
    
            while (cas.iterator().hasNext()){ 
    
                ConfigAttribute ca = iterator.next();
    
                String needRole = ca.getAttribute();
    
                //访问的路径存在,但是没有登录
                if ("ROLE_LOGIN".equals(needRole)){
                    if (auth instanceof AnonymousAuthenticationToken){
                        throw new BadCredentialsException("未登录");
                    }
                    return;
                }
    
                //登录了,访问的路径也存在,但是要判断时候又该权限进行访问
                Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
                for (GrantedAuthority authority : authorities) {
                    if (authority.getAuthority().equals(needRole)){ //如果具有的角色是之前登录的角色的一种就可以访问
                        return;
                    }
                }
    
            }
    
            throw new AccessDeniedException("访问权限不足");
    
        }
    
        @Override
        public boolean supports(ConfigAttribute configAttribute) {
            return false;
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return false;
        }

    至此,项目的整体搭建基本ok。

  • 相关阅读:
    侃一侃WebSocket
    为什么我要用GoEasy替代WebSocket
    WebSocket负载均衡
    大道至简 知易行难 JAVA 完成WebSocket demo 用GoEasy实现Hello world
    大道至简 知易行难 C# 完成WebSocket demo 用GoEasy实现Hello world
    WebSocket跨域问题解决
    WebSocket原理
    WebSocket 和HTTP的区别及原理
    WebSocket与Socket、TCP、HTTP的关系和异同点
    WebSocket配置中会遇到的一些问题
  • 原文地址:https://www.cnblogs.com/gfbzs/p/12346898.html
Copyright © 2011-2022 走看看