实现未登录跳转到登录界面的方法有很多,例如后端框架使用springsecurity来实现安全框架
java复制代码 @Override
protected void configure(HttpSecurity http) throws Exception {
// 表单认证
http.formLogin()
.successForwardUrl("/welcome") //登录成功后,跳转到指定请求(此处是 post 请求)
.failureForwardUrl("/loginFail")//登录失败
.loginPage("/login.html");
但是,咱们的系统是前后端分离的,实现上面的逻辑很复杂,所以结合这个项目,我觉得自己开发一套登录权限认证功能。 首先我们要知道前后端分离一般使用json和浏览器cookie来交换数据,所以这里我们需要前后端一起来配合完成这个功能。
第一步,我们在JWTAuthenticationFilter类中定义登录成功的方法
java复制代码 // 成功验证后调用的方法
// 如果验证成功,就生成token并返回
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) {
JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
System.out.println("jwtUser:" + jwtUser.toString());
boolean isRemember = rememberMe.get() == 1;
String role = "";
Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
for (GrantedAuthority authority : authorities) {
role = authority.getAuthority();
}
String token = JwtTokenUtils.createToken(jwtUser.getUsername(), role, isRemember);
// 返回创建成功的token
// 但是这里创建的token只是单纯的token
// 按照jwt的规定,最后请求的时候应该是 `Bearer token`
String authToken = JwtTokenUtils.TOKEN_PREFIX + token;
String result = JSONObject.toJSONString(ResponseUtils.success(authToken));
try {
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
这里的作用就是我们登录成功后会返回jwt产生的token值
第二步,我们在前端登录成功的时候将这个值存储在cookie中去
java复制代码import Cookies from 'js-cookie'
const TokenKey = 'Authorization'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
这个是auth.js用来利用js-cookie来操作浏览器token的
java复制代码methods: {
login() {
if (this.loginForm.username === "" || this.loginForm.password === "") {
alert("账号或密码不能为空");
} else {
loginvalidate(this.loginForm)
.then((res) => {
console.log("rerer", res)
if (res.code === "0000") {
setToken(res.data);
this.$router.push("/homePage")
} else {
alert("账号或密码错误");
}
})
.catch((error) => {
alert("系统出现错误");
console.log(error);
});
}
},
setToken方法就能将后端返回回来的token存储到cookie中 这里不了解的可以去这篇专栏的上两篇去了解一下
第三步,这步我称为拦截器
在发送和接收后端返回的数据的时候进行拦截
java复制代码import axios from 'axios'
import { getToken } from './auth'
import Router from "vue-router";
//创建axios实例
const service = axios.create({
baseURL: '/api',
timeout: 10000
})
// request interceptor
service.interceptors.request.use(
config => {
config.headers.Authorization = getToken()
// do something before request is sent
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
response => {
const res = response.data
console.log("res",response);
if (res.code === "0401"){
new Router().push("/");
location.reload();
}
return res;
},
error => {
console.log('err' + error) // for debug
}
)
export default service
这里的意思(service.interceptors.request.use)就是在每个请求头中加入配置 这个意思(service.interceptors.response.use)就是在每个返回信息中中修改配置 这里有个大坑:就是config.headers.Authorization = getToken()这里,一点要每次都调用方法一下,不能够这样写:
java复制代码let AUTH_TOKEN = getToken()
config.headers.Authorization = AUTH_TOKEN
这个真的是坑死我了,花费了我一天时间去找这个bug(每次登录的时候都会拿不到cookie)
java复制代码 if (res.code === "0401"){
new Router().push("/");
location.reload();
}
这里的意思就是当我检测返回的数据里面的code值为0401的时候(自己后端定义的)就会push到登录页面 这样,我们每次在token删除或者token失效的时候返回后端的接口,然后后端就会发现没有权限,就会返回0401转态码给前端,前端接受处理之后就会push到登录页面,这样就实现了检测到未登录自动跳转到登录页面的功能啦! 更多的代码我开了个仓库供大家参考
前端仓库地址:
后端仓库地址: