zoukankan      html  css  js  c++  java
  • springsecurity 总结

    spring security是安全框架,最常使用的是认证和授权,认证是登录操作,授权是针对请求访问的限制。

    在项目开发中正常情况下,认证和授权需要自定义一些功能

    认证

    登录逻辑(实现UserDetailsService接口)

    从数据库中获取数据

    @Component
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Autowired
        private UserMapper userMapper;
        @Autowired
        private RoleMapper roleMapper;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //根据username获取user信息
            com.marw.sys.entity.User user=userMapper.findUserByUsername(username);
    
            if(user==null){
                throw new UsernameNotFoundException("用户不存在");
            }
    
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            //根据UserID获取菜单
            List<RoleExtendMap> menuList = roleMapper.findRoleByUsreId(user.getId());
    
            SecurityUser securityUser = new SecurityUser(user, menuList);
            return securityUser;
        }
    }

    授权

    登录前操作(UsernamePasswordAuthenticationFilter过滤器中attemptAuthentication方法)

    获取表单提交的用户名和密码

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            if (this.postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            } else {
                String username = this.obtainUsername(request);
                username = username != null ? username : "";
                username = username.trim();
                String password = this.obtainPassword(request);
                password = password != null ? password : "";
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            }
        }

    登录成功操作,登录失败操作(在UsernamePasswordAuthenticationFilter父类

    AbstractAuthenticationProcessingFilter过滤器中successfulAuthentication、unsuccessfulAuthentication方法)

        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
            SecurityContextHolder.getContext().setAuthentication(authResult);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authResult));
            }
    
            this.rememberMeServices.loginSuccess(request, response, authResult);
            if (this.eventPublisher != null) {
                this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
            }
    
            this.successHandler.onAuthenticationSuccess(request, response, authResult);
        }
    
        protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) 
            throws IOException, ServletException { SecurityContextHolder.clearContext(); this.logger.trace("Failed to process authentication request", failed); this.logger.trace("Cleared SecurityContextHolder"); this.logger.trace("Handling authentication failure"); this.rememberMeServices.loginFail(request, response); this.failureHandler.onAuthenticationFailure(request, response, failed); }

    自定义登录前、登录成功和登录失败操作就可以继承UsernamePasswordAuthenticationFilter并重写这三个方法

    授权设置(BasicAuthenticationFilter过滤器中doFiler)

    授权的本质:权限信息交给权限上下文

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
            try {
                UsernamePasswordAuthenticationToken authRequest = this.authenticationConverter.convert(request);
                if (authRequest == null) {
                    this.logger.trace("Did not process authentication request since failed to find username and password in Basic Authorization header");
                    chain.doFilter(request, response);
                    return;
                }
    
                String username = authRequest.getName();
                this.logger.trace(LogMessage.format("Found username '%s' in Basic Authorization header", username));
                if (this.authenticationIsRequired(username)) {
                    Authentication authResult = this.authenticationManager.authenticate(authRequest);
                   //权限信息存储在权限上下文中  
              SecurityContextHolder.getContext().setAuthentication(authResult);
    if (this.logger.isDebugEnabled()) { this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authResult)); } this.rememberMeServices.loginSuccess(request, response, authResult); this.onSuccessfulAuthentication(request, response, authResult); } } catch (AuthenticationException var7) { SecurityContextHolder.clearContext(); this.logger.debug("Failed to process authentication request", var7); this.rememberMeServices.loginFail(request, response); this.onUnsuccessfulAuthentication(request, response, var7); if (this.ignoreFailure) { chain.doFilter(request, response); } else { this.authenticationEntryPoint.commence(request, response, var7); } return; } chain.doFilter(request, response); }

    未授权(实现AuthenticationEntryPoint接口)

    public class Http403ForbiddenEntryPoint implements AuthenticationEntryPoint {
        private static final Log logger = LogFactory.getLog(Http403ForbiddenEntryPoint.class);
    
        public Http403ForbiddenEntryPoint() {
        }
    
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) throws IOException {
            logger.debug("Pre-authenticated entry point called. Rejecting access");
            response.sendError(403, "Access Denied");
        }
    }

    SpringSecurity配置类

    作用:设置认证和授权

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private UserDetailsService userDetailsServiceImpl;//自定义认证操作
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            //指定认证和加密方式
            auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(passwordEncoder());
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.exceptionHandling().authenticationEntryPoint(new 自定义未授权类)
                    .addFilter(new 自定义过滤器);//可以实现认证前后操作和授权数据的设置
        }
    
        @Bean
        public PasswordEncoder passwordEncoder(){
            //return new BCryptPasswordEncoder();
            //自定义MD5加密
            return new MD5PasswordEncoder();
        }
    }
  • 相关阅读:
    抄来的
    getWindowHandle();
    tcp协议
    同学少年多不贱
    蓝桥 算法训练 最短路
    洛谷P1460 健康的荷斯坦奶牛 Healthy Holsteins
    蓝桥 算法提高 学霸的迷宫
    初等数论 ————拓展欧几里得算法
    CF1037D Valid BFS?
    1053 Path of Equal Weight
  • 原文地址:https://www.cnblogs.com/WarBlog/p/15165634.html
Copyright © 2011-2022 走看看