express-sso

145 阅读5分钟
//首先,我们需要安装一些依赖:

//Express框架:用于构建Web应用程序
//npm install express --save
//Passport模块:用于处理认证和授权
//npm install passport passport-saml express-session --save
//用于存储和读取cookie的中间件
//npm install cookie-parser --save
//接下来,我们创建一个名为app.js的文件,并添加以下代码:

const express = require("express");
const passport = require("passport");
const SamlStrategy = require("passport-saml").Strategy;
const cookieParser = require("cookie-parser");
const session = require("express-session");
 
// 创建Express应用程序
const app = express();
 
// 配置视图引擎
app.set("view engine", "html");
app.engine("html", require("ejs").renderFile);
 
// 设置cookie解析器和会话中间件
app.use(cookieParser());
app.use(
  session({
    secret: "yourSecretKey",
    resave: false,
    saveUninitialized: true,
  })
);
 
// 配置Passport和SAML策略
passport.use(
  new SamlStrategy(
    {
      // ADFS提供的元数据URL
      entryPoint: "https://sts.secsso.net/adfs/ls",
      issuer: "yourIssuer",
      callbackUrl: "http://localhost:3000/login/callback",
      cert: "yourSigningCertificate",
    },
    function (profile, done) {
      // 在这里处理验证成功后的逻辑
      // 可以根据需要从profile中取出相关的用户信息并保存在cookie中
      return done(null, profile);
    }
  )
);
 
// 初始化Passport
app.use(passport.initialize());
app.use(passport.session());
 
// 序列化和反序列化用户对象
passport.serializeUser(function (user, done) {
  done(null, user);
});
 
passport.deserializeUser(function (user, done) {
  done(null, user);
});
 
// 定义登录和回调路由
app.get("/login", passport.authenticate("saml"));
app.post(
  "/login/callback",
  passport.authenticate("saml", { failureRedirect: "/", successRedirect: "/" })
);
 
// 定义默认路由,重定向到登录
app.get("/", function (req, res) {
  res.redirect("/login");
});
 
// 启动服务器
app.listen(3000, function () {
  console.log("Server started on port 3000");
});

在上面的代码中,我们首先引入所需的模块,然后创建一个Express应用程序。我们设置了视图引擎为HTML,并配置了cookie解析器和会话中间件。

接下来,我们配置Passport和SAML策略。在SAML策略的构造函数中,我们提供了ADFS的元数据URL、签名证书等配置信息。在验证成功后的回调函数中,我们可以根据需要从profile对象中获取相关的用户信息,并将其保存在cookie中。

然后,我们初始化Passport,并设置了序列化和反序列化用户对象的逻辑。

接着,我们定义了登录和回调路由。当用户访问/login路由时,Passport会将用户重定向到ADFS进行登录。登录成功后,ADFS会将用户重定向回我们指定的回调URL,并在URL中包含SAML响应。我们在回调路由中通过调用passport.authenticate方法来处理SAML响应,如果验证失败则重定向到登录页面,如果验证成功则重定向到系统的入口页面。

最后,我们定义了默认路由,当用户访问系统时会自动重定向到登录页面。

你需要将yourIssuer和yourSigningCertificate替换为实际的值。yourIssuer是你的应用程序的标识符,yourSigningCertificate是你使用的签名证书。

同时,你还需要创建一个名为login.html的HTML文件,作为登录页面。在该文件中,你需要添加一个登录按钮,点击按钮时将用户重定向到/login路由。

在使用Express框架实现登录功能前,需要先安装相应的依赖包。在项目根目录下打开命令行,执行以下命令:

npm install express express-session passport passport-saml --save
安装完成后,可以开始编写代码了。首先,在根目录下创建一个名为index.js的文件,并添加以下代码:

const express = require('express');
const passport = require('passport');
const SamlStrategy = require('passport-saml').Strategy;
const session = require('express-session');
 
const app = express();
 
// 设置SAML配置信息
const samlConfig = {
  entryPoint: 'https://sts.secsso.net', // SSO服务提供商的登录地址
  issuer: 'http://localhost:3000', // 本系统的标识
  callbackUrl: 'http://localhost:3000/login/callback', // 登录成功后的回调URL
};
 
// 配置SAML策略
passport.use(new SamlStrategy(
  {
    ...samlConfig,
    // 验证SAML响应中的用户信息
    verify: (profile, done) => {
      // 在此处验证用户信息,并将用户信息传递给回调函数
      done(null, profile);
    },
  },
));
 
// 序列化和反序列化用户信息
passport.serializeUser((user, done) => {
  done(null, JSON.stringify(user));
});
 
passport.deserializeUser((user, done) => {
  done(null, JSON.parse(user));
});
 
// 配置Express中间件
app.use(session({ secret: 'secret-key', resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
 
// 登录页面路由
app.get('/login', passport.authenticate('saml'));
 
// 登录回调路由
app.post('/login/callback', passport.authenticate('saml', { failureRedirect: '/login' }), (req, res) => {
  // 登录成功后的逻辑,将用户信息保存在cookie中
  res.cookie('user', JSON.stringify(req.user));
  res.redirect('/home');
});
 
// 主页路由
app.get('/home', (req, res) => {
  // 在这里获取用户信息
  const user = JSON.parse(req.cookies.user);
  res.send(`Welcome, ${user.displayName}!`);
});
 
// 退出登录路由
app.get('/logout', (req, res) => {
  // 清除cookie中的用户信息
  res.clearCookie('user');
  res.redirect('/login');
});
 
// 启动服务
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
在项目根目录下创建一个名为login.html的文件,作为登录页面,内容如下:

<!DOCTYPE html>
<html>
<head>
  <title>Login</title>
</head>
<body>
  <h1>Login Page</h1>
  <form method="post" action="/login">
    <button type="submit">Login</button>
  </form>
</body>
</html>
现在运行项目,打开浏览器访问http://localhost:3000,将会自动跳转到https://sts.secsso.net进行登录。登录成功后,将会跳转回本地服务器,并显示欢迎信息。

要退出登录,可以访问http://localhost:3000/logout,将会清除cookie中的用户信息,并重定向到登录页面。

////////////////////////////////////////////////////////////////////////////////////////

mkdir sso-example
cd sso-example
npm init -y
npm install express passport passport-saml express-session
 
 
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const SAMLStrategy = require('passport-saml').Strategy;
 
const app = express();
app.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: true
}));
 
const samlConfig = {
  entryPoint: 'YOUR_ADFS_ENTRY_POINT',
  issuer: 'YOUR_ISSUER_NAME',
  cert: 'YOUR_CERT_CONTENTS'
};
 
passport.use(new SAMLStrategy(samlConfig, (profile, done) => {
  // 在这里验证用户信息并进行相关操作
  return done(null, profile);
}));
 
passport.serializeUser((user, done) => {
  done(null, user);
});
 
passport.deserializeUser((user, done) => {
  done(null, user);
});
 
app.use(passport.initialize());
app.use(passport.session());
 
app.get('/', (req, res) => {
  if (req.isAuthenticated()) {
    res.send('Authenticated User: ' + req.user.email);
  } else {
    res.redirect('/login');
  }
});
 
app.get('/login', passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }));
 
app.post('/login/callback',
  passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }),
  (req, res) => {
    res.redirect('/');
  }
);
 
app.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});
 
app.listen(3000, () => {
  console.log('Server started on http://localhost:3000');
});
 
 
 
<!DOCTYPE html>
<html>
<head>
  <title>Login Page</title>
</head>
<body>
  <h1>Login Page</h1>
  <!-- Add your login form here -->
</body>
</html>
 
在上述代码中,同样需要替换 YOUR_ADFS_ENTRY_POINTYOUR_ISSUER_NAMEYOUR_CERT_CONTENTS。

这个示例中使用了 express-session 来管理用户会话,而不是直接将用户信息保存在 cookie 中。当用户通过 ADFS 认证成功后,passport-saml 模块会将用户信息存储在会话中。如果用户已经通过认证,则直接展示用户信息;否则,重定向到 /login 路由进行认证。

最后,在命令行中执行 node app.js 启动应用程序。当访问 http://localhost:3000 时,如果未进行认证,将会自动跳转到 ADFS 登录页面进行认证。认证成功后,用户信息将存储在会话中,可以通过访问 http://localhost:3000 查看认证用户信息。