一.后端(Spingboot)
1.定义注解
2.定义TokenService类
@Service
public class TokenService {
//生成token
public String getToken(User user){
String token = "";
token = JWT.create().withAudience(user.getUserName()).sign(Algorithm.HMAC256(user.getUserPassword()));
return token;
}
}
3.编写拦截器
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
UserMapper userMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");//获取token
//不为映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if(method.isAnnotationPresent(PassToken.class)){
PassToken passToken = method.getAnnotation(PassToken.class);
if(passToken.required()){
return true;
}
}
//检测是否有需要用户权限的注解
if(method.isAnnotationPresent(UserLoginToken.class)){
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if(userLoginToken.required()){
//执行认证
if(token == null){
throw new RuntimeException("401");
}
//获取token中的username
String userName;
try{
userName = JWT.decode(token).getAudience().get(0);
}catch (JWTDecodeException j){
throw new RuntimeException("401");
}
User user = userMapper.selectUserByName(userName);
if(user == null){
throw new RuntimeException("401");
}
//验证token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getUserPassword())).build();
try{
jwtVerifier.verify(token);
}catch (JWTVerificationException e){
throw new RuntimeException("401");
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
4.配置拦截器
@Configuration
public class MyPicConfig implements WebMvcConfigurer {
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
//拦截所有请求,判断是否有@LoginRequired注解决定是否需要登录
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**");
}
}
5.使用
(1)不加@UserLoginToken注解默认通过
@PostMapping("/login")
public Object login(@RequestBody User user){
JSONObject jsonObject = new JSONObject();
User userForBase = userMapper.selectUserByName(user.getUserName());
if(userForBase == null){
jsonObject.put("message","登录失败,用户不存在");
return jsonObject;
}else{
if(!userForBase.getUserPassword().equals(user.getUserPassword())){
jsonObject.put("message","登录失败,密码错误");
return jsonObject;
}
else{
if(userForBase.getUserGrade() == 0){
jsonObject.put("message","您的信用分数过低,已被网站拦截");
return jsonObject;
}
String token = tokenService.getToken(userForBase);
jsonObject.put("token",token);
jsonObject.put("user",userForBase);
return jsonObject;
}
}
}
(2)添加注解则需要进行token检测
@UserLoginToken
@GetMapping("/getMessage")
public String getMessage(){
return "你已通过验证";
}
二.前端(vue)
1.配置vuex(store/index.js)
export default new Vuex.Store({
state: {
token: localStorage.getItem('token')?localStorage.getItem('token'):'',
},
mutations: {
setToken(state,token){
state.token = token;
localStorage.setItem("token",token);
},
delToken(state){
state.token = '';
localStorage.removeItem('token');
}
},
actions: {
},
modules: {
}
})
2.添加拦截器(main.js)
axios.interceptors.request.use(config => {
//判断是否存在token,如果存在将每个页面header都添加token
if(store.state.token){
config.headers.common['Authorization'] = store.state.token
}
return config;
}, error => {
});
// http response 拦截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.data.message) {//若message为404则返回登录页
case '401':
store.commit('delToken');
router.replace('/login');
}
}
});
3.使用
login(){
if(!(this.userName!=''&&this.password!='')){
this.$message("请输入账号与密码!");
return;
}
let url = 'http://localhost:8080/user/login'
axios.post(url,{userName:this.userName,userPassword:this.password}).then(res=>{
if(res.data['message']){
this.$message(res.data['message']);
return;
}
let token = res.data['token'];//token
this.$store.commit('setToken',token);
//console.log(window.localStorage['token']); 可以直接获取token值
//console.log(this.$store.state.token);
window.localStorage.setItem("username",this.userName);
this.$router.push('/forum');
}).catch(err=>{
console.log(err);
})
}
三.参考文章
1.SpringBoot集成JWT实现token验证
2.Vue项目中的token验证登录(前端部分)