SpringMVC文件上传
思路:
1、首先定义页面,定义多功能表单(enctype=“multipart/form-data”)
2、在Controller里面定义一个方法,用参数(MultipartFile)来接收前台传递过来的文件对象
3、然后文件上传就是把文件从一个地方(本地)复制到另外一个地方(服务器)
首先添加pom依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
springmvc.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 文件最大大小(字节) 1024*1024*50=50M-->
<property name="maxUploadSize" value="52428800"></property>
<!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常-->
<property name="resolveLazily" value="true"/>
</bean>
upload.jsp
<form action="/book/upload" method="post" enctype="multipart/form-data">
请选择文件:<input type="file" name="xxx">
<input type="submit" value="ok">
</form>
@RequestMapping("/upload")
public String upload(HttpServletRequest req, MultipartFile xxx){
String fileName=xxx.getOriginalFilename();
String contentType=xxx.getContentType();
try {
FileUtils.copyInputStreamToFile(xxx.getInputStream(),new File("D:\liuxia"+fileName));
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/book/list";
}
Jwt身份验证
什么是Jwt
JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案
JWT的精髓在于:“去中心化”,数据是保存在客户端的。
JWT的工作原理
是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,示例如下:
{“UserName”: “Chongchong”,“Role”: “Admin”,“Expire”: “2018-08-08 20:15:56”}
之后,当用户与服务器通信时,客户在请求中发回JSON对象
为了防止用户篡改数据,服务器将在生成对象时添加签名,并对发回的数据进行验证
Jwt组成:一个JWT实际上就是一个字符串,它由三部分组成:头部(Header)、载荷(Payload)与签名(signature)
Jwt实现登录验证
思路:
登录界面向后台请求验证码,后台就先调用随机函数生成验证码,并且根据验证码生成一张图片,以 base64 字符串的形式传到前台,这时我们还要生成verificationJwt令牌做为请求验证码客户端的区分。我们先将验证码信息存入redis。key是 verificationJwt令牌的值,value就是验证码了。并且将令牌放入到响应头。传给客户端。当客户端提交的时候将保持的verificationJwt令牌放入请求头带过来。后端根据前端传过来的 jwt令牌去redis中获取数据,将验证码拿到后和现有的验证码进行比较。看看是否相等
细节:
访问一次登录页面,生成一个verificationJwt令牌,这个令牌的有效时间是5min,验证码在redis中的有效时间是1min,无论是verificationJwt令牌超时失效,还是验证码生成后超时失效,都会造成登录失败;
简单来说就是跳转到登陆界面,需要在5min中之内完成登录,新的验证码出来后,需要在1min中之内完成登录
逻辑图如下
效果图:
Pom依赖
<!--引入JWT依赖,由于是基于Java,所以需要的是java-jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
前端:
State.js
export default {
resturantName: '飞歌餐馆',
jwt:'',
options: [],//存放tab页的容器
activeIndex: '',//激活的tab页路由路径
showName:'show',//tab页的标题
role:"",//用来区分是否是因为左侧菜单被点击造成的路由路径发生改变,是:pass;不是:nopass
verificationJwt:null, //这是用来保存用户等登录验证码jwt身份识别的
}
Mutations.js
setVerificationJwt: (state, payload) => {
state.verificationJwt = payload.verificationJwt;
}
Getters.js
getVerificationJwt:(state) =>{
return state.verificationJwt;
}
action.js
export default {
// 'SERVER': 'http://localhost:8080/T216_SSH', //服务器
'SERVER': 'http://localhost:8080', //服务器
// 'SYSTEM_USER_DOLOGIN': '/vue/userAction_login.action', //用户登陆
'SYSTEM_USER_DOLOGIN': '/vue/user/login', //用户登陆
'VERIFICATION': '/vue/user/verificationCode', //用户登陆
'SYSTEM_USER_DOREG': '/vue/userAction_reg.action', //用户注册
'SYSTEM_MENU_TREE': '/vue/treeNodeAction.action', //左侧树形菜单加载
'SYSTEM_ARTICLE_LIST': '/vue/articleAction_list.action', //文章列表
'SYSTEM_ARTICLE_ADD': '/vue/articleAction_add.action', //文章新增
'SYSTEM_ARTICLE_EDIT': '/vue/articleAction_edit.action', //文章修改
'SYSTEM_ARTICLE_DEL': '/vue/articleAction_del.action', //文章删除
'SYSTEM_USER_GETASYNCDATA': '/vue/userAction_getAsyncData.action', //vuex中的异步加载数据
'getFullPath': k => { //获得请求的完整地址,用于mockjs测试时使用
return this.SERVER + this[k];
}
}
http.js
// 请求拦截器
axios.interceptors.request.use(function(config) {
//设置验证码jwt令牌
let verificationJwt = window.vm.$store.getters.getVerificationJwt;
if (verificationJwt) {
config.headers['verificationJwt'] = verificationJwt;
}
var jwt = window.vm.$store.getters.getJwt;
config.headers['jwt'] = jwt;
return config;
}, function(error) {
return Promise.reject(error);
});
// 响应拦截器
axios.interceptors.response.use(function(response) {
// debugger;
//保存验证码jwt令牌
let verificationjwt = response.headers['verificationjwt'];
if (verificationjwt) {
window.vm.$store.commit('setVerificationJwt', {
verificationJwt: verificationjwt
});
}
var jwt = response.headers['jwt'];
if (jwt) {
window.vm.$store.commit('setJwt', {
jwt: jwt
});
}
return response;
}, function(error) {
return Promise.reject(error);
});
Login.vue
<template>
<div class="login-wrap">
<el-form class="login-container">
<h1 class="title">用户登录</h1>
<el-form-item label="">
<el-input type="text" v-model="userName" placeholder="请输入登录账号" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="">
<el-input type="password" v-model="userPwd" placeholder="请输入登录密码" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="">
<el-row>
<el-col :span="16">
<el-input type="text" v-model="verificationCode" placeholder="请输入验证码" autocomplete="off"></el-input>
</el-col>
<el-col :span="8">
<img id="img" :src="verificationCodeSrc" width="116px" height="40px" @click="changeVerificationCode" >
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width: 100%;" @click="doSubmit">登 录</el-button>
</el-form-item>
<el-row style="text-align: center; margin-top: -15;">
<el-link type="primary">忘记密码</el-link>
<el-link type="primary" @click="gotoRegister">用户注册</el-link>
</el-row>
</el-form>
</div>
</template>
<script>
export default {
name: 'Login',
data: function() {
return {
userName: null,
userPwd: null,
verificationCode:null,
verificationCodeSrc:null
}