SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)

文章目录

    • 关联数据库实现登录
      • 在common包下新建自定义的用户登录实现类
        • service层的变化:
        • 自定义异常进行统一处理【自定义异常】(新建子包exception处理器)
          • 在Security的配置类中添加如下代码:
    • 前端登录的测试:
          • ①、输入错误时
          • ②、输入正确时
          • ③、输入正确【但是账户未激活时】
    • JWT认证过滤器实现
        • 前端中修改登录成功的跳转
          • ①、新建layout目录并新建index.vue【带有布局的首页】
          • ②、后台中控制器编写一个请求
          • ③、在router中index.js中更改主入口的路由
          • ④、Login.vue中更新路由
          • ⑤、测试是否能够正常请求并响应数据
    • 定义过滤器
        • 在common子包下新建过滤器
          • 需要将登录成功的处理器的token的定值进行动态的修改:
          • 在Security的配置类中进行注入以及添加自定义过滤器
          • 然后重新启动并登录即可
    • JWT认证异常的处理器实现
        • 在common子包下新建一个类对象实现异常处理
          • 修改Security的配置类
          • 定义好异常处理的对象
          • 最后重新启动并访问 [可以将登录成功的token进行修改]
    • 自定义注销logout处理实现
          • 修改Security中的配置类:
          • 前端index.vue中编写接口进行测试:
          • 测试注销接口
    • 小结

关联数据库实现登录

提示:这里穿插了数据库持久层的操作,使用MybatisPlus框架作为数据库持久层的技术,熟悉掌握它吧!!!

在common包下新建自定义的用户登录实现类

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第1张图片

package com.xuguoguo.common;


import com.xuguoguo.entity.SysUser;
import com.xuguoguo.exception.UserCountLockException;
import com.xuguoguo.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 @Package: com.xuguoguo.common
 @ClassName: ResponseData
 @Author: XuGuoGuo
 @CreateTime: 2023/12/12-20:26
 @Description:  自定义UserDetails
 */
@Service
public class MyUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    SysUserService sysUserService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser=sysUserService.getByUsername(username);
        if(sysUser==null){
            throw new UsernameNotFoundException("用户名或者密码错误!");
        }else if("1".equals(sysUser.getStatus())){
            throw new UserCountLockException("该用户账号被封禁,具体请联系管理员!");
        }
        return new User(sysUser.getUsername(),sysUser.getPassword(),getUserAuthority());
    }

    public List<GrantedAuthority> getUserAuthority() {
        return new ArrayList<>();
    }
}
service层的变化:
public interface SysUserService extends IService<SysUser> {

    SysUser getByUsername(String username);
}

/**
* @author xuguoguo
* @description 针对表【sys_user】的数据库操作Service实现
* @createDate 2023-12-05 20:20:08
*/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
    implements SysUserService{

    @Override
    public SysUser getByUsername(String username) {
        return getOne(new QueryWrapper<SysUser>().eq("username",username));
    }
}
自定义异常进行统一处理【自定义异常】(新建子包exception处理器)

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第2张图片

public class UserCountLockException extends AuthenticationException {

    public UserCountLockException(String msg, Throwable t) {
        super(msg, t);
    }

    public UserCountLockException(String msg) {
        super(msg);
    }
}
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = RuntimeException.class)
    public Result handler(RuntimeException e){
        log.error("项目运行时异常:--------->{}"+e.getMessage());
        return Result.error(e.getMessage());
    }
}
在Security的配置类中添加如下代码:

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第3张图片

@Autowired
private MyUserDetailsServiceImpl myUserDetailsService;

//密码加密处理方式
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
    return  new BCryptPasswordEncoder();
}


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(myUserDetailsService);
}

前端登录的测试:

此时数据表的记录:[密码是加密后的123456]

在这里插入图片描述

①、输入错误时

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第4张图片

②、输入正确时

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第5张图片

③、输入正确【但是账户未激活时】

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第6张图片

JWT认证过滤器实现

提示:这里还是需要使用到springsecurity中的认证的内容块,需要多理解它!!!

前端中修改登录成功的跳转
①、新建layout目录并新建index.vue【带有布局的首页】

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第7张图片

②、后台中控制器编写一个请求

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第8张图片

③、在router中index.js中更改主入口的路由

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第9张图片

④、Login.vue中更新路由

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第10张图片

⑤、测试是否能够正常请求并响应数据

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第11张图片

由此可知,直接响应回SpringSecurity的默认登录页面,这样是不行的!

定义过滤器

在common子包下新建过滤器

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第12张图片

package com.xuguoguo.common;

import com.xuguoguo.entity.SysUser;
import com.xuguoguo.service.SysUserService;
import com.xuguoguo.utils.JwtUtils;
import com.xuguoguo.utils.StringUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

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

/**
 @Package: com.xuguoguo.common
 @ClassName: MyJwtAuthenticationFilter
 @Author: XuGuoGuo
 @CreateTime: 2023/12/6-19:19
 @Description:
 */
@Slf4j
public class MyJwtAuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private MyUserDetailsServiceImpl myUserDetailsService;

    private static final String URL_WHITELIST[] ={
            "/login",
            "/logout",
            "/captcha",
            "/password",
            "/image/**"
    } ;

    public MyJwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String token = request.getHeader("token");
        System.out.println("请求url:"+request.getRequestURI());
        // 如果token是空 或者 url在白名单里,则放行
        if(StringUtil.isEmpty(token) || new ArrayList<String>(Arrays.asList(URL_WHITELIST)).contains(request.getRequestURI())){
            chain.doFilter(request,response);
            return;
        }
        try {
            Claims claims = JwtUtils.parseJWT(token);
            log.info("正在执行jwt认证过滤:{}",claims.toString());
            String username = claims.getSubject();
            SysUser sysUser = sysUserService.getByUsername(username);
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=new UsernamePasswordAuthenticationToken(username,null,
                    //========  此处预留根据用户编号查询用户拥有的权限信息 ========
                    myUserDetailsService.getUserAuthority());
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            chain.doFilter(request,response);
        } catch (ExpiredJwtException e) {
            throw new JwtException("Token过期");
        } catch (SignatureException e) {
            throw new JwtException("Token验证不通过");
        } catch (Exception e) {
            throw new JwtException("Token不存在");
        }
    }
}
需要将登录成功的处理器的token的定值进行动态的修改:

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第13张图片

在Security的配置类中进行注入以及添加自定义过滤器

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第14张图片
在这里插入图片描述

@Bean
MyJwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
    MyJwtAuthenticationFilter jwtAuthenticationFilter=new MyJwtAuthenticationFilter(authenticationManager());
    return jwtAuthenticationFilter;
}
//===========================自定义过滤器配置=========================
        .and()
        .addFilter(jwtAuthenticationFilter());
然后重新启动并登录即可

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第15张图片

JWT认证异常的处理器实现

在common子包下新建一个类对象实现异常处理

@Component
public class MyJwtAuthenticationEntryPoint  implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        ResponseData<Object> result = new ResponseData<>
                ("请求异常",HttpServletResponse.SC_UNAUTHORIZED,"认证失败,请登录!");
        String jsonStr = JSONUtil.toJsonStr(result);
        outputStream.write(jsonStr.getBytes("UTF-8"));
        outputStream.flush();
        outputStream.close();
    }
}
修改Security的配置类

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第16张图片

定义好异常处理的对象

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第17张图片

最后重新启动并访问 [可以将登录成功的token进行修改]

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第18张图片
SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第19张图片

自定义注销logout处理实现

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第20张图片

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                                Authentication authentication) throws IOException, ServletException {
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        outputStream.write(JSONUtil.toJsonStr(Result.ok("注销成功")).getBytes());
        outputStream.flush();
        outputStream.close();
    }
}
修改Security中的配置类:

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第21张图片
SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第22张图片

前端index.vue中编写接口进行测试:

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第23张图片

测试注销接口

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第24张图片

小结

提示:这个小结中主要实现了是使用了数据库的用户信息表来实现登录,并且自定义了用户过滤认证、认证异常处理以及注销的基本的操作实现引导!!!

本章的第四小节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码或者工具的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!

SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(四)_第25张图片

你可能感兴趣的:(SpringSecurity,MybatisPlus,SpringBoot,spring,boot,后端,java,mysql,restful,web,app)