前端部分
- 页面部分
//登录页
账号:<input type="text" id="username"><br>
密码:<input type="password" id="password"><br>
<button type="button" id="login" onclick="login()">登录</button>
<script type="text/javascript" src="js/jquery1.8.3.min.js"></script>
<script type="text/javascript" src="js/path.js"></script>
<script type="text/javascript" src="js/login.js"></script>
//显示页
<div id="div">
<table align="center">
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>地址</td>
<td>操作</td>
</tr>
<tbody id="tables">
</tbody>
</table>
</div>
- js部分
//path.js 用于统一后端请求接口的前缀路径(jsp页面是有自动加前缀的)
var path="http://localhost:8080/ssmredis2/";
//login.js 登录js文件
function login(){
var username=$("#username").val();
var password=$("#password").val();
$.ajax({
type:'post',
url:path+'admin/login',
data:{
"username":username,
"password":password
},
success:function(d){
var code=d.code;//响应状态码
var msg=d.msg;//响应信息
var token=d.k;//响应token
localStorage.setItem("ken",token);//token存入localStorage
if(code==200){//成功
alert(msg);
window.location.href="show.html";//跳转页面
} else {
alert(msg);
}
}
});
}
//show.js 显示页js
$(document).ready(function(){
//进入show.html会自动执行的函数,该函数是请求服务端方法
var token=localStorage.getItem("ken");//从localStorage中取出token
$.ajax({
type:'post',
url:path+'admin/selectStudent',
data:{
"token":token//发送token以在后端过滤器中验证token
},
success:function(d){
var code=d.code;//响应状态码
var msg=d.msg;//响应信息
if(code==200){
parseJson(d);//调用解析json的方法
} else if(code==300){//未登录状态
window.location.href="index.html";//跳转首页
}
}
})
})
/*解析json*/
//由于多处需使用渲染数据(渲染代码相同),写一个公共函数进行渲染
function parseJson(d){
var list=d.result;//获取服务端响应数据中的 列表数据
var f="";
//将列表数据写到页面中
for(var i = 0; i < list.length; i++){
f+="<tr>";
f+="<td>"+list[i].name+"</td>";
f+="<td>"+list[i].sex+"</td>";
f+="<td>"+list[i].age+"</td>";
f+="<td>"+list[i].address+"</td>";
f+="<td><a href='javascript:;;' οnclick='deleteUser("+list[i].id+")'>删除</a></td>";
f+="</tr>";
}
$("#tables").html(f);
}
后端部分
1.SpringMVC拦截器
//登录不进行登录 spring-mvc.xml中配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/admin/login"/>
<bean class="interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
//拦截器preHandle方法中
Map<String, Object> map=new HashMap<String, Object>();
try {
//每次请求携带本地中的toke请求
String token=request.getParameter("token");
System.out.println(token);
//token为空为未登录,如:换浏览器进行登录
if (token==null||"".equals(token)) {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
map.put("code", 300);
map.put("msg", "未登录状态");
out.print(JSONObject.fromObject(map));
return false;
}
//获取token中的username,本次为模拟数据实际开发中为数据主键id(uuid)
String username=token.split(",")[1];
//此处为判断username在redis中是否存在(向redis中存值时使用的是username),实际中为主键id进行判断(向redis中存值时使用的是主键id)
if (!redisTemplate.hasKey(username)) {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
map.put("code", 300);
map.put("msg", "未登录状态");
out.print(JSONObject.fromObject(map));
return false;
}
//单点登录,但同为一个用户是主键id相同,redis中的token不同时无法在多端进行操作
String serviceToken=redisTemplate.opsForValue().get(username);
if (!serviceToken.equals(token)) {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
map.put("code", 300);
map.put("msg", "未登录状态");
out.print(JSONObject.fromObject(map));
return false;
}
redisTemplate.expire(username, 30, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
e.printStackTrace();
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
map.put("code", 300);
map.put("message", "未登录状态");
out.print(JSONObject.fromObject(map));
return false;
}
- 跨域的设置
//手写拦截器 doFilter中配置
HttpServletResponse myResponse = (HttpServletResponse) arg1;
myResponse.setHeader("Access-Control-Allow-Origin", "*");
myResponse.setHeader("Access-Control-Allow-Methods", "*");
myResponse.setHeader("Access-Control-Max-Age", "3600");
myResponse.setHeader("Access-Control-Allow-Headers", "*");
myResponse.setHeader("Access-Control-Allow-Credentials", "true");
//web.xml 中配置
<filter>
<filter-name>CORS</filter-name>
<filter-class>utils.ResponseHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 请求的方法
//用于操作redis数据库
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private StudentService studentService;
//此处为模拟数据 登录方法
@RequestMapping(value = "login",method = RequestMethod.POST)
public Map<String, Object> login(String username,String password,HttpServletResponse response){
Map<String, Object> map=new HashMap<String, Object>();
if ("1".equals(username)&&"1".equals(password)) {
//实际开发中token为主键id+随机的uuid
String token=UUID.randomUUID().toString().replaceAll("-", "")+","+username;
//实际开发中username为主键id
redisTemplate.opsForValue().set(username, token);
redisTemplate.expire(username, 30, TimeUnit.SECONDS);
map.put("code",200);
map.put("msg","登陆成功");
map.put("k",token);
System.out.println(map.get("k"));
} else {
map.put("code",201);
map.put("msg","账号或密码错误");
}
return map;
}
//查询信息
@RequestMapping("selectStudent")
public Map<String, Object> selectStudent(HttpServletRequest request,HttpServletResponse response) {
Map<String, Object> map=new HashMap<String, Object>();
Student stu=new Student();
List<Student> list=studentService.findStudent(stu);
map.put("code",200);
map.put("msg","查询成功");
map.put("result",list);
return map;
}
本次redis操作使用的是redisTemplate,登录时向redis数据库中存入token同时也向前端发送token,前端获取token存入localStorage中,每次请求都需要取出加入ajax请求数据中,登录验证拦截器中只做了向前端返回json数据,实际跳转页面由js来判断完成,但需要进入某些页面中如未登录状态需跳转到登录页时可以只在前端中判断localStorage中是否有token。
如在a浏览器中进行登录,b浏览器中没有登录过,在进入b浏览器时会自动进入登录页,因为b浏览器localStorage中没有token