springboot实现token登录

2022年8月17日13:16:13

一、Controller层login接口进行账密验证,验证成功返回token

配置文件:
springboot实现token登录
最主要是第一个依赖,后面不属于jsonwebtoken的依赖
controller:

@PostMapping("/login")
    public Result<TokenStatus> login(@RequestBody LoginVO loginVO, HttpServletRequest request) {
        Result<TokenStatus> result = new Result<>();
        UserDO userDO = null;
        try {
            userDO = userService.getUser(loginVO, request);
        } catch (NirException e) {
            result.setCode(e.getCode());
            result.setMsg(e.getMessage());
            return result;
        } catch (Exception e) {
            result.setCode(NirExceptionEnum.GENERAL_EXCEPTION.getCode());
            result.setMsg(e.getMessage());
            return result;
        }
        TokenStatus tokenStatus = JwtUtil.createJwt(userDO.getId().toString(),userDO.getUsername());
        result.setData(tokenStatus);
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(ResultEnum.SUCCESS.getMsg());
        return result;
    }

JwtUtil类


public class JwtUtil {
    public static final String KEY = "userlogin";
    public static final Long FAILURE_TIME = 3600000L;

    public static TokenStatus createJwt(String id, String username){
        TokenStatus tokenStatus = new TokenStatus();
        long now = System.currentTimeMillis();
        long exp = now + FAILURE_TIME;
        Date date = new Date(exp);
        JwtBuilder jwtBuilder = Jwts.builder().setId(id).setSubject(username)
                .setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256,KEY);
        jwtBuilder.setExpiration(date);
        String token = jwtBuilder.compact();
        tokenStatus.setToken(token);
        tokenStatus.setExp(date);
        return tokenStatus;
    }

    public static Claims parseJwt(String token){
        Claims claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token).getBody();
        return claims;
    }

}

二、前端login接口返回token,存进cookie

let param = {
        username: values.username,
        password: values.password,
      };
      API.login(param)
        .then((res) => {
          const { code, msg, data} = res;
          if (code !== "200") {
            Message.error("登录失败,用户名或密码错误!");
          } else {
            Message.success("登录成功!");
            if(data.token&&data.exp){
              document.cookie = "token="+ data.token+";expires="+new Date(data.exp).toGMTString();
            }
            this.props.history.push('/home');
          }
        })
        .catch((err) => {
          Message.error(err + "登录失败!请重试!");
        });

退出登录清除cookie中的token,跳转到登录页面

logout = () => {
    deleteCookie("token");
    this.props.history.replace("/login");
  };
export const deleteCookie = (name) => {
  var exp = new Date();
  exp.setTime(exp.getTime()-1);
  var val = getCookie(name);
  if(val!=null){
    document.cookie= name + "="+val+";expires="+exp.toGMTString();
  }
}

export const getCookie = (name) => {
  var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
  if(arr=document.cookie.match(reg))
    return unescape(arr[2]);
  else
    return null;
}

给每个请求添加请求头Authorization,加上token

headers: {
        "Content-Type": "application/json",
        'Authorization': getCookie("token") ,
        "withCredentials": true,
      },

三、前端对路由模块进行封装,对cookie里不存在token的页面不允许访问,跳转到登录页面

import  React from 'React';
import { Route, Redirect } from 'react-router-dom';
import { Message } from 'antd';
import { getCookie } from "../pages/home/Home";

const PrivateRoute = ({component: Component, ...props}) => {
    // 解构赋值 将 props 里面的 component 赋值给 Component
    return <Route {...props} render={(p) => {
        const token = getCookie("token");
        if (token){ // 如果登录了, 返回正确的路由
            if(props.path==='/login'){
                return <Redirect to='/home'/>
            }else{
                return <Component />
            }
        } else { // 没有登录就重定向至登录页面
            Message.error("你还未登录,请先登录")
            return <Redirect to='/login'/>
        }
    }}/>
}
export default PrivateRoute

使用方法:

<Route path="/login" component={Login}></Route>
<Route path="/register" component={Register}></Route>
 <PrivateRoute path="/admin" component={Admin}></PrivateRoute>
 <PrivateRoute path="/home" component={Home}></PrivateRoute>

四、后端添加过滤器,对没带token的请求和token不符合要求的请求进行过滤处理,返回未登录提示

此处的过滤器采用javax.servlet.Filter的接口实现

@WebFilter(urlPatterns = {"/user/getUser","/record/*","/patient/*","/disease/*"})
public class TokenFilter implements Filter {
    @Autowired
    private UserDOMapper userMapper;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String token = httpServletRequest.getHeader("Authorization");
        try{
            if(token==null || token.equals("null")){
                throw new NirException(NirExceptionEnum.USER_UNLOGIN);
            }else{
                UserDOExample example = new UserDOExample();
                String username = JwtUtil.parseJwt(token).getSubject();
                example.createCriteria().andUsernameEqualTo(username);
                List<UserDO> users = userMapper.selectByExample(example);
                if (CollectionUtils.isEmpty(users)) {
                    throw new NirException(NirExceptionEnum.USER_UNLOGIN);
                }else{
                    filterChain.doFilter(servletRequest,servletResponse);
                }
            }
        }catch(NirException e){
            Result<Void> result = new Result<>();
            result.setCode(e.getCode());
            result.setMsg(e.getMessage());
            httpServletResponse.setHeader("content-type", "application/json;charset=utf-8");
            httpServletResponse.setHeader("Access-Control-Allow-Origin","*");
            httpServletResponse.setHeader("Access-Control-Allow-Methods","POST,OPTIONS");
            httpServletResponse.setHeader("Access-Control-Allow-Credentials","true");
            httpServletResponse.setHeader("Access-Control-Allow-Headers","Content-Type,WithCredentials,Authorization");
            PrintWriter out = httpServletResponse.getWriter();
            out.println(JSON.toJSONString(result));
        }
    }

    @Override
    public void destroy() {

    }
}

这样就实现了一个系统的的token登录功能。

  • 作者:菜鸟的传奇人生
  • 原文链接:https://blog.csdn.net/qq_40820235/article/details/110525784
    更新时间:2022年8月17日13:16:13 ,共 4931 字。