1、编写登录页面,让自己的页面有权限管理功能。
基础登录功能:
重新创建一个LoginController:
@Slf4j
@RestController
public class LoginController {
@Autowired
private ReaderService readerService;
@PostMapping("/login")
public Result login(@RequestBody Reader reader){
//将json格式的数据封装到实体类中,添加注解@RequestBody
log.info("员工登录:{}",reader);
Reader r = readerService.login(reader);
return r != null? Result.success():Result.error("用户名或密码错误!");
//如果r不为空,则返回success,否则返回error
}
}
ReaderService:
public interface ReaderService {
//员工登录操作
public Reader login(Reader reader);
}
ReaderServiceImpl:
@Service
public class ReaderServiceImpl implements ReaderService {
@Autowired
private ReaderMapper readerMapper;
@Override
public Reader login(Reader reader) {
return readerMapper.getByUsernameAndPassword(reader);
}
}
ReaderMapper:
@Mapper
public interface ReaderMapper {
@Select("select * from reader where username = #{username} and password = #{password}")
public Reader getByUsernameAndPassword(Reader reader);
}
postman测试:
登录校验:
浏览器与服务器之间进行交互是经过HTTP协议的,http协议又是无状态的,每一次请求都是独立的,不会携带上一次请求的数据。
服务端要想判断用户是否已经登录,就要在用户登录成功之后存储一个登录标记。统一拦截技术来拦截浏览器发送过来的所有的请求,拦截到请求后就可以对这个请求进行校验是否登录,获取之前所存入的登录标记,获取到则说明该用户已经登录,否则前端跳转到登录页面。
会话技术:
会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
会话跟踪:一种维护浏览器状态的方法,服务器只需要识别多此请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。
客户端会话跟踪技术:cookie
浏览器第一次发起请求来请求服务器的时候设置一个cookie存储相关的数据信息,服务器会自动的将cookie响应给浏览器,浏览器将返回cookie的值自动的存储在本地,后续的每一次请求浏览器会自动的将本地存储的cookie又携带到服务端,服务端判断该cookie之前是否存在,若不存在说明该客户端之前没有访问登录接口的,若存在则已登录。
响应头:(set-Cookie:name=value)
请求头:(Cookie:name=value)
优点:HTTP协议中支持的技术
缺点:移动端APP无法使用Cookie,不安全(用户可以自己禁用Cookie),不能跨域。
服务端会话跟踪技术:session
浏览器在第一次请求服务器时,服务器创建会话对象session,每一个session都有一个id,服务器端给浏览器响应数据时会将id通过Cookie响应给浏览器,(Set-Cookie:JSESSION=1),浏览器接收到响应数据后自动将Cookie存储在浏览器本地,在后续的每一次请求都会将Cookie的数据获取出来并且带到服务端,服务器拿到session的id会从众多的session中找到当前请求的会话对象session。
优点:存储在服务端,安全
缺点:服务器集群环境下无法直接使用Session,Cookie的缺点
令牌技术
如果登录成功,则生产一个令牌,为该用户的合法身份凭证,响应数据时将令牌直接响应给前端,前端接收到后将令牌存储起来,之后的每一次请求都要将令牌携带到服务端,校验令牌的有效性,有效则已经执行了登录操作,无效说明并未登录,共享的数据也可以储存在令牌中。
优点:支持pc端、移动端,解决集群环境下的认证问题,减轻服务器端存储的压力。
缺点:需要自己实现。
JWT令牌:
JSON Web Token 一种简洁的,自包含的格式,用于在通信双方以json数据格式安全的传输信息。
组成:header(头)、payload(有效载荷)、signature(签名)
场景:登录认证
登录成功后,生成令牌;后续每个请求,都要携带JWT令牌,系统在每次出来请求之前,先校验令牌,通过后,再处理。
JWT-生成和校验
pom文件中引入依赖后编写测试类:
在官网解析后:
jwt-校验:
controller中实现:
@Slf4j
@RestController
public class LoginController {
@Autowired
private ReaderService readerService;
@PostMapping("/login")
public Result login(@RequestBody Reader reader){
//将json格式的数据封装到实体类中,添加注解@RequestBody
log.info("员工登录:{}",reader);
Reader r = readerService.login(reader);
//登录成功,生成令牌,下发令牌
if(r != null){
Map<String,Object> claims = new HashMap<>();
claims.put("id",r.getId());
claims.put("username",r.getUsername());
String jwt = JwtUtils.generateJwt(claims);
return Result.success(jwt);
}
//登陆失败,返回错误信息
return Result.error("用户名或密码错误!");
}
}
postman测试:用户名密码正确,成功下发jwt令牌
编写页面:读者的账号密码正确,登录信息写入session中,则每个页面课可以通过读取session信息判断是否为有权限。如果没有写入session,或者session信息被清除了,则通过判断确定没有权限访问。
实现:
当输入用户名和密码时:
跳转到index1成功登录:
且在控制台输出:
跳转到index2:
点击退出登录后:
当输入错误的密码时:
且在控制台输出:
代码:
index1.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>必须成功登录才能访问</title>
<link rel="stylesheet" href="js/element.css">
<script src="js/jquery.min.js"></script>
<script src="js/vue.js"></script>
<script src="js/element.js"></script>
<script src="js/axios-0.18.0.js"></script>
</head>
<body>
<div id="app">
<div v-if="tableData.code==1">
<h1 align="center">页面1--成功</h1>
<a href="index2.html">页面2</a>
<a href="logout">退出登录</a>
<h2 align="center">我天你竟然登录成功了,下面是登录信息展示~</h2>
<table border="1" align="center" width="800px">
<tr>
<th>code</th>
<th>msg</th>
<th>data</th>
</tr>
<tr>
<td>{{tableData.code}}</td>
<td>{{tableData.msg}}</td>
<td>{{tableData.data}}null</td>
</tr>
</table>
</div>
<div v-else-if="tableData.code==0">
code={{tableData.code}}没有权限访问!sorry啦!
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
tableData: {
code:"" ,
msg:"" ,
data:""
}
},
mounted() {
var url = `/index1`
axios.get(url)
.then(response => {
this.tableData = response.data;
console.log(this.tableData);
})
.catch(error=>{
console.error(error);
})
}
})
</script>
</body>
</html>
index2.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>必须成功登录以后才能访问</title>
<link rel="stylesheet" href="js/element.css">
<script src="js/jquery.min.js"></script>
<script src="js/vue.js"></script>
<script src="js/element.js"></script>
<script src="js/axios-0.18.0.js"></script>
</head>
<body>
<div id="app">
<div v-if="tableData.code==1">
<h1 align="center">页面2--成功</h1>
<a href="index1.html">页面1</a>
<a href="logout">退出登录</a>
<h2 align="center">我天index2你竟然也登录成功了,下面是登录信息展示~</h2>
<table border="1" align="center" width="800px">
<tr>
<th>code</th>
<th>msg</th>
<th>data</th>
</tr>
<tr>
<td>{{tableData.code}}</td>
<td>{{tableData.msg}}</td>
<td>{{tableData.data}}null</td>
</tr>
</table>
</div>
<div v-else-if="tableData.code==0">
{{tableData.code}}没有权限访问!
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
tableData: {
code:"" ,
msg:"" ,
data:""
}
},
mounted() {
var url = `/index2`
axios.get(url)
.then(response => {
//this.tableData = response.data;
this.tableData = response.data;
console.log(this.tableData);
})
.catch(error=>{
console.error(error);
})
}
})
</script>
</body>
</html>
ReaderSessionController:
package com.example.librarymasterlendlist.Controller;
import com.example.librarymasterlendlist.Pojo.Reader;
import com.example.librarymasterlendlist.Pojo.Result;
import com.example.librarymasterlendlist.Service.ReaderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
public class LoginSessionController {
@Autowired
private ReaderService readerService;
@PostMapping("/login_session")
public Result login(HttpServletRequest request, @RequestBody Reader readers){
Reader r = readerService.login(readers);
if (r != null){
request.getSession().setAttribute("reader",readers.getUsername());
String reader = (String)request.getSession().getAttribute("reader");
System.out.println("查询不为空" + reader);
return Result.success();
}
else {
String reader = (String)request.getSession().getAttribute("reader");
System.out.println("查询为空" + reader);
return Result.error("用户名或密码错误");
}
}
@GetMapping("/logout")
public Result logout(HttpServletRequest request){
//清理Session中保存的当前登录员工的id
request.getSession().removeAttribute("reader");
return Result.success("退出成功");
}
@GetMapping("/index1")
public Result index1(HttpServletRequest request) {
String reader = (String) request.getSession().getAttribute("reader");
if (reader != null) {
return Result.success();
} else {
return Result.error("无权限");
}
}
@GetMapping("/index2")
public Result index2(HttpServletRequest request) {
String reader = (String) request.getSession().getAttribute("reader");
if (reader != null) {
return Result.success();
} else {
return Result.error("无权限");
}
}
}
ReaderService、ReaderServiceImpl、ReaderMappert同上。
2、将自己的项目改造为基于vue-cli脚手架的项目,页面有导航,学会使用router
index.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: '/lend'
},
{
path: '/reader',
name: 'reader',
component: () => import( '../views/library_lend/ReaderView.vue')
},
{
path: '/lend',
name: 'lend',
component: () => import( '../views/library_lend/LendView.vue')
}
]
const router = new VueRouter({
routes
})
export default router
添加<router-link to="/xxx"></router-link>标签