SSO单点登录(以下全是个人理解,如果有误,共同批评进步)
1.什么是单点登录:
在不同的应用中,受保护的同一用户,登录一次就可以访问相关的其他系统应用。比如搜狐登录后,可以直接访问博客、邮箱等等,而不用再重新登录博客系统、邮箱系统等等。方便了用户的操作。
2.同域下单点登录实现:
单点登录流程和大概思路如下:
我们用具体代码来实现以下操作:
我们有四个项目,app1、app2、ssofilter、ssoserver分别是web系统1、web系统2、拦截请求系统、sso认证中心。
app1系统结构如下:
就一个jsp文件,用来获取用户信息。app2系统的页面也一样。
我们先写sso认证中心的代码,这里只写主要的代码:
登录的代码,登录成功后写入cookie,将令牌和用户信息存入全局信息中
/**
* get请求,表示没有登录直接访问。获取路径,返回登录页面
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求路径
String backurl=request.getParameter("backurl");
request.setAttribute("backurl", backurl);
request.getRequestDispatcher("index.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决中文乱码
request.setCharacterEncoding("utf-8");
String username=request.getParameter("username");
String password=request.getParameter("password");
String backurl=request.getParameter("backurl");
try {
User user=new User();
//根据用户名名称查询用户
user = UserUtil.getUserByname(username);
if(null!=user&& password.equals(user.getPassword())){
System.out.println("登录成功!");
/*String[] uuid=UUID.randomUUID().toString().split("-");
StringBuffer token=new StringBuffer();
for (String string : uuid) {
token.append(string);
}*/
//生成令牌,根据java生成uuid,将其中的-符号替换为空字符串,然后转成小写字母
String token=UUID.randomUUID().toString().replace("-", "").toLowerCase();
//根据自定义的全局工具类,将令牌作为key,将用户信息作为value存入Map中
MapUtil.addToken(token, user);
//创建一个cookie
Cookie cookie=new Cookie("token", token);
cookie.setHttpOnly(true);
cookie.setPath("/");
//将cookie添入响应中,返回客户端
response.addCookie(cookie);
if(StringUtils.isNullOrEmpty(backurl)){
//如果没有获取到请求路径,表示用户直接访问login登录页面,这里可以将值设置为登录成功后的主页
backurl="success";
}else{
//将路径解码
backurl=URLDecoder.decode(backurl,"utf-8");
}
//重新定向到返回路径
//response.sendRedirect(backurl);
response.getWriter().println(backurl);
}else{
response.setContentType("text/html;utf-8");
response.setCharacterEncoding("utf-8");
System.out.println("用户名或密码不对!");
response.getWriter().println("用户名或密码不对");
}
} catch (SQLException e) {
e.printStackTrace();
}
SSO认证中心,验证代码:
//获取请求令牌
String token=request.getParameter("token");
//根据令牌去请求对应的用户信息
User user=MapUtil.getUserByToken(token);
//判断令牌是否有效
if(null!=user){
//有效,返回用户信息
response.getWriter().println("username="+URLEncoder.encode(user.getUsername(),"utf-8")+";password="+user.getPassword());
}else{
//无效,返回空字符串
response.getWriter().println("");
}
拦截请求系统代码:
//将ServletRequest和ServletResponse转为Http请求的
HttpServletRequest httprequest=(HttpServletRequest)request;
HttpServletResponse httpresponse=(HttpServletResponse)response;
//获取cookie数组
Cookie[] cookies=httprequest.getCookies();
String token=null;
if(null!=cookies && 00){
String[] userdata=stringbuffer.split(";");
User user=new User();
for (String string : userdata) {
String[] string2=string.split("=");
switch (string2[0]){
case "username":
user.setUsername(URLDecoder.decode(string2[1],"utf-8"));
break;
case "password":
user.setPassword(string2[1]);
break;
}
}
request.setAttribute("user", user);
filter.doFilter(httprequest, httpresponse);
}else{
//标示token无效,将请求定向到登录地址
httpresponse.sendRedirect(SSOLOGINURL+"?backurl="+URLEncoder.encode(url,"utf-8"));
}
}
将
拦截请求系统打成jar包,加入web1和web2中使用,在web1和web2中配置拦截器
loginfilter
com.client.ssoFilter
loginfilter
*.jsp
还有SSO认证中心的登录页面:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
登录