首页 > 解决方案 > 使用 Express 和 GraphQL 的 Windows 身份验证

问题描述

我正在尝试为我的 React 应用程序(使用 apollo 客户端)实现窗口身份验证。我apollo graphql server用作后端。我曾经node-sspi让 Windows 登录用户。

下面是我的服务器端代码。http://localhost:9000/graphiql如果添加则不起作用app.use(function (req, res, next) {。也没有让 windows 登录用户名。

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');

const port = process.env.PORT || 9000;
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')

const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

// authentication middleware
const authMiddleware = expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
})

app.use(cors(), bodyParser.json(), authMiddleware);

app.use(function (req, res, next) {
  var nodeSSPI = require('node-sspi')
  var nodeSSPIObj = new nodeSSPI({
    retrieveGroups: true
  })
  nodeSSPIObj.authenticate(req, res, function(err){
    res.finished || next()
  })
})

const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user && db.students.get(req.user.sub)}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

app.post('/login', (req, res) => {
   const userName = req.connection.user; // USERNAME undefined
   // LDAP Authenticate 
   const token = jwt.sign({sub: userName}, jwtSecret);
   res.send({token});
});

app.listen(
   port, () => console.info(
      `Server started on port ${port}. use http://localhost:${port}/graphiql`
   )
);

标签: node.jsexpressgraphql

解决方案


在做了一些解决方法后我得到了解决方案。

服务器端代码

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');

const port = process.env.PORT || 9000;
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')

const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

// authentication middleware
const authMiddleware = expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
})

app.use(cors(), bodyParser.json(), authMiddleware);

//Setup endpoint routes
var router = express.Router();
//Basic Router Config
router.use(function(req, res, next){

   var nodeSSPI = require('node-sspi')
   //Integrated Authentication for Windows
   var nodeSSPIObj = new nodeSSPI({
       retrieveGroups: true
   });

   try{
       nodeSSPIObj.authenticate(req, res, function(err){
           res.finished || next();
       });
   }
   catch(err)
   {
       res.status(500).send(JSON.stringify({status: 500, message: "Something went wrong", detail: err.message}));
   }
});

// windows
router.get('/', function(req, res){
   // Do LDAP authentication or whatever

   const token = jwt.sign({authUser: req.connection.user}, jwtSecret);
   res.send({token});
});

// Regular login
router.post('/login', (req, res) => {
   const email = req.body.email;
   const password = req.body.password;

   const user = authenticateUser // SQL/mongo/etc..
   const token = jwt.sign({authUser: user.id}, jwtSecret);
   res.send({token});
});

app.use('/api', router);

const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user && req.user.authUser}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

app.listen(
   port, () => console.info(
      `Server started on port ${port}. use http://localhost:${port}/graphiql`
   )
);

在客户端,我使用 Ajax Jquery 调用 POC。

对于windows登录

$.ajax({
url: "http://localhost:9000/api",
contentType: "application/json",
xhrFields: {
  withCredentials: true
},
type: "GET",
data: '',
success: function (response) {
  loginToken = response.token;
      },
error: (xhr, err) => alert('error')
})

使用登录凭据

var email =  $("#txtEmail").val();
var password =  $("#txtPwd").val();
if(email && password) {
   $.ajax({
      url:"http://localhost:9000/api/login",
      contentType:"application/json",
      type:"POST",
      xhrFields: {
             withCredentials: true
      },
      data:JSON.stringify({email,password}),
      success:function(response) {
             loginToken =  response.token;   
      },
      error:(xhr,err) =>  alert('error')
      })
}else alert("email and pwd empty")

对于 GraphQL 查询

$.ajax({url: "http://localhost:9000/graphql",
        contentType: "application/json",
        headers: {"Authorization": 'bearer '+ loginToken},
        type:'POST',
        data: JSON.stringify({
        query:`{greetingWithAuth}` }),
        success: function(result) {
                  console.log(result.data.greetingWithAuth")
        },
        error: func
       }

推荐阅读