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

SpringBoot集成Security框架 2022.3.24

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

SpringBoot集成Security框架 2022.3.24

SpringBoot集成Security框架 1、核心配置详解 1)SecurityConfig(security配置):主要用来对Security整体进行配置,要继承WebSecurityConfigurerAdapter类,在configure方法中可以对跨域,接口请求资源放行,异常处理,过滤器进行配置。也可以在类中通过 @Bean注解注入所要使用的Bean到容器中进行使用,比如AuthenticationManager(用来对用户的认证)和PasswordEncoder(对密码进行加密)类。 2)JwtFilter(jwt过滤器):在用户名和密码过滤器(UsernamePasswordAuthenticationFilter(security自带的))之前对请求进行拦截,对请求携带的token进行拦截判断。JwtFilter类继承OncePerRequestFilter类并实现doFilterInternal方法,对请求进行过滤。 3)UserDetailsServiceImpl:需要实现UserDetailsService类,目的是用来完成用户在登录对数据库用户的查询,在登录方法中AuthenticationManager(认证管理器)会自动调用这个实现类进行查询。UserDetailsServiceImpl的返回结果应该是UserDetails的实现类,因此需要单独写一个类UserDetailImpl来实现UserDetails(用来封装用户信息)。 4)UserDetailImpl:用来对用户认证身份进行封装,包括权限、用户名,密码、账号过期锁定等等。用来把autenticate.getPrincipal()对象转换成UserDetailImpl的用户对象,这里之所以这样,是因为security内部是通过UserDetails实现的,我们实现了UserDetails这个类,所以可以用UserDetailImpl进行封装。 5)WebUtils(封装了统一的返回方法):用来对security发生异常时,对数据的返回 6)AccessDeniedHandlerImpl:访问拒绝的实现类,用来对访问拒绝的异常进行返回(主要是权限异常)。需要实现AccessDeniedHandler,并且实现其中的handle方法。这个方法中会调用WebUtils中的方法。 6)AuthenticationEntryPointImpl:处理认证异常的实现类,需要实现AuthenticationEntryPoint类,用来对认证过程中的异常信息进行处理并返回,需要实现commence方法,方法中会调用WebUtils中方法。 2、核心配置代码 1)SecurityConfig
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private JwtFilter jwtFilter;

    @Resource
    AuthenticationEntryPoint authenticationEntryPoint;
    @Resource
    AccessDeniedHandler accessDeniedHandler;

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

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                //.antMatchers("/login").anonymous()

        
                //.antMatchers("/login","/doc.html","/webjars
    public static void renderString(HttpServletResponse response, String string) {
        try
        {
            response.setStatus(200);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }


    public static void setDownLoadHeader(String filename, ServletContext context, HttpServletResponse response) throws UnsupportedEncodingException {
        String mimeType = context.getMimeType(filename);//获取文件的mime类型
        response.setHeader("content-type",mimeType);
        String fname= URLEncoder.encode(filename,"UTF-8");
        response.setHeader("Content-disposition","attachment; filename="+fname);

//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setCharacterEncoding("utf-8");
    }
}
6)AccessDeniedHandlerImpl
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        //打印下异常
        accessDeniedException.printStackTrace();
        ResponseResult result = ResponseResult.fail(ResponseCode.UNAUTHORI.code,ResponseCode.UNAUTHORI.msg);
        //以json的形式相应给前端
        WebUtils.renderString(response, JSONUtil.toJsonStr(result));
    }
}
7)AuthenticationEntryPointImpl
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        //打印下异常
        authException.printStackTrace();
        //登录认证是根据不同的情况,提示不同的错误
        ResponseResult result = null;
        //BadCredentialsException密码错误的异常,坏的凭据
        //InsufficientAuthenticationException,凭据不足
        if(authException instanceof BadCredentialsException){
            result = ResponseResult.fail(ResponseCode.FAIL.code,authException.getMessage());
        }else if(authException instanceof InsufficientAuthenticationException){
            result = ResponseResult.fail(ResponseCode.UNLOGIN.code,authException.getMessage());
        }else{
            result = ResponseResult.fail(ResponseCode.FAIL.code,"认证和授权出线问题");
        }
        //以json的形式相应给前端
        WebUtils.renderString(response, JSONUtil.toJsonStr(result));
    }
}
3、注意事项

在使用UsernamePasswordAuthenticationToken进行用户和密码认证时,需要调用AuthenticationManager认证管理器进行管理,在这个过程中一定不能忘记实现UserDetailsServiceImpl和UserDetailImpl类,不然会走默认的认证流程,这时候就查询不到用户数据,会报出Handler dispatch failed; nested exception is java.lang.StackOverflowError这个异常

4、自定义登录
@Service//这里是user的业务层,用的mybatisplus
public class UserServiceImpl extends ServiceImpl implements IUserService {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public ResponseResult login(UserDto userDto) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDto.getUserName(),userDto.getUserPass());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
//            throw new BadCredentialsException("用户名或密码错误");
            return ResponseResult.fail(ResponseCode.FAIL.code,"账号或密码错误");
        }
        UserDetailImpl userDetail = (UserDetailImpl)authenticate.getPrincipal();
        String userId = userDetail.getUser().getUserId().toString();
        String jwt = JwtUtil.createJWT(userId);
        return ResponseResult.success(MapUtil.builder().put("token",jwt).build());
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778759.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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