SpringBoot + SpringSecurity 实现安全认证

## 导入maven依赖

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


package com.cloud.common;

import com.cloud.config.filter.CkCodeAuthenticationFilter;
import com.cloud.config.filter.InitialAuthenticationFilter;
import com.cloud.config.filter.JwtAuthenticationFilter;
import com.cloud.config.handler.CustAuthFailHandler;
import com.cloud.config.handler.CustAuthSuccHandler;
import com.cloud.config.provider.OptAuthProvider;
import com.cloud.config.provider.UsernamePasswordAuthProvider;
import com.cloud.sys.dto.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;

import javax.sql.DataSource;
import java.util.Arrays;


/**
 * @author haizhuangbu
 * @date 2022/4/28 09:29
 * @mark WebConfig
 */
@Configuration
public class WebConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private OptAuthProvider optAuthProvider;
    @Autowired
    private UsernamePasswordAuthProvider usernamePasswordAuthProvider;

    @Autowired
    private CustAuthSuccHandler authenticationSuccessHandler;
    @Autowired
    private CustAuthFailHandler authenticationFailureHandler;
    @Autowired
    private InitialAuthenticationFilter initialAuthenticationFilter;
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    @Autowired
    private CkCodeAuthenticationFilter ckCodeAuthenticationFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 数据库实现 验证方式
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("select USER_NAME,USER_PASS,USER_ENABLE\n" +
                        "from S_USR where USER_NAME = ?")
                .authoritiesByUsernameQuery("\n" +
                        "select AUTH_ROLE,S_AUTH.USER_NAME\n" +
                        "from S_AUTH where S_AUTH.USER_NAME = ?")
                .passwordEncoder(new MyPasswordEncoder())
                .rolePrefix("ADMIN");
        auth.authenticationProvider(optAuthProvider)
                .authenticationProvider(usernamePasswordAuthProvider);

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单验证 设置放通路径 
        http.authorizeRequests()
                .mvcMatchers("image/**", "/error", "/image/**", "/file/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
//  设置拦截类
                .addFilterBefore(ckCodeAuthenticationFilter, BasicAuthenticationFilter.class)
                .addFilterAt(initialAuthenticationFilter, BasicAuthenticationFilter.class)
                .addFilterAfter(jwtAuthenticationFilter, BasicAuthenticationFilter.class)
                .formLogin()
// 配置成功|失败跳转逻辑
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler);
//                .and().csrf().disable();
    }


    @Override
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}


// 验证过程
package com.cloud.config.filter;

import com.cloud.config.handler.CkCodeFailHandler;
import com.cloud.sys.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author haizhuangbu
 * @date 2022/6/6 18:18
 * @mark CkCodeAuthenticationFilter
 */
@Component
public class CkCodeAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private CkCodeFailHandler ckCodeFailHandler;

    @Autowired
    private ProductService webScoketService;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        logger.info("================== 执行验证码校验 =======================");
        String key = request.getParameter("imgKey");
        String value = request.getParameter("imgValue");
        ValueOperations str = redisTemplate.opsForValue();
        String code = str.get(key);
//        assert code != null;
        if (code == null || !code.equalsIgnoreCase(value)) {
            webScoketService.sendAll(request.getParameter("username") + " : " + "验证码校验失败");
            ckCodeFailHandler.onAuthenticationFailure(request, response, new BadCredentialsException("验证码校验错误"));
            return;
        }
        webScoketService.sendAll(request.getParameter("username") + " : " + "验证码校验成功");
        chain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return !request.getServletPath().equals("/login");
    }
}


// 登陆成功逻辑
package com.cloud.config.handler;

import com.alibaba.fastjson.JSONObject;
import com.cloud.common.JwtUtils;
import com.cloud.sys.dto.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author haizhuangbu
 * @date 2022/6/2 22:25
 * @mark CustAuthSuccHandler 登录成功逻辑
 */
@Service
public class CustAuthSuccHandler implements AuthenticationSuccessHandler {

    private Logger logger = LoggerFactory.getLogger(CustAuthSuccHandler.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        logger.info("================ 执行登录成功逻辑 ===================");
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();
        // 跳转
        User user = new User();
        user.setAuth(authentication);
        String jwt = JwtUtils.createJwt(user);
        response.setHeader("authentication", jwt);
        logger.info("============== 存储token =======================");
        ValueOperations string = redisTemplate.opsForValue();
        string.set(jwt, "1", 600, TimeUnit.SECONDS);

        HashMap map = new HashMap<>();
        map.put("code", HttpStatus.OK);
        map.put("success", true);
        map.put("message", "loginSuccess");
        outputStream.print(JSONObject.toJSONString(map));
        outputStream.flush();
        outputStream.close();
    }
}


// 登陆失败
package com.cloud.config.handler;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * @author haizhuangbu
 * @date 2022/6/2 22:25
 * @mark CustAuthSuccHandler 登录失败逻辑
 */
@Service
public class CustAuthFailHandler implements AuthenticationFailureHandler {

    private Logger logger = LoggerFactory.getLogger(CustAuthFailHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        PrintWriter writer = response.getWriter();
//        ServletOutputStream outputStream = response.getOutputStream();
        HashMap map = new HashMap<>();
        map.put("code", HttpStatus.INTERNAL_SERVER_ERROR);
        map.put("success", false);
        map.put("message", e.getMessage());
        writer.print(JSONObject.toJSONString(map));
        response.sendRedirect("/login");
        writer.flush();
        writer.close();
    }
}


你可能感兴趣的:(SpringBoot + SpringSecurity 实现安全认证)