在访问带有[Authorize]的方法的时候,需要前端通过自定义报文头的形式将JWT令牌传递给后端进行验证,否则是不能访问带有[Authorize]的方法。
[Authorize]是用于限制对web应用程序中某些操作或控制器的访问。当[授权]属性应用于操作或控制器时,它表示用户必须经过身份验证和授权才能访问该特定资源。还可以使用其他参数自定义此属性,以根据特定角色或策略进一步限制访问。
但是Websocket是不支持自定义报文头的,所以我们只能通过url将JWT令牌进行传递。
这里创建了一个实现SignalR的方法,该方法带有[Authorize],功能是前端传递什么返回什么。
public class Myhub : Hub
{[Authorize]public Task SendPublicMsg(string msg){string msgToSend = msg;return Clients.All.SendAsync("publicMsgReceived", msgToSend);}
}
在Program.cs中的配置
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();//JWT配置
builder.Services.Configure<JWTSettings>(builder.Configuration.GetSection("JWT"));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{var jwtSettings = builder.Configuration.GetSection("JWT").Get<JWTSettings>();byte[] keyBytes = Encoding.UTF8.GetBytes(jwtSettings.SecKey);var secKey = new SymmetricSecurityKey(keyBytes);opt.TokenValidationParameters = new(){ValidateIssuer=false,ValidateAudience=false,ValidateLifetime=true,ValidateIssuerSigningKey=true,IssuerSigningKey=secKey};opt.Events = new JwtBearerEvents{//Websocket不支持自定义报文头OnMessageReceived = context =>{var accessToke = context.Request.Query["access_token"];//取出JWTvar path = context.Request.Path;if (!string.IsNullOrEmpty(accessToke) && path.StartsWithSegments("/Myhub")){context.Token = accessToke;}return Task.CompletedTask;}};
});builder.Services.AddSignalR();//调用SignalR
builder.Services.AddMemoryCache();
app.UseCors();app.UseHttpsRedirection();app.UseAuthentication();app.UseAuthorization();app.MapHub<Myhub>("/Myhub");app.MapControllers();app.Run();
前端
界面
<div><button @click="JwtItem">连接</button><button @click="sendMessage">发送</button><input type="text" v-model="sigtext"/><p v-for="i in msgs">{{i}}</p>
</div>
该连接要在后端返回你的JWT令牌后进行连接
startConnection() {var options={skipNegotiation:true,transport:signalR.HttpTransportType.WebSockets};//this.JWTkey你的JWT令牌options.accessTokenFactory=()=>this.JWTkey;//创建连接this.connection = new signalR.HubConnectionBuilder()//大括号里面强制执行Websockets通道(解决分布式问题).withUrl('https://localhost:44334/Myhub',options) .withAutomaticReconnect() //断开自动连接.build();//注册this.connection.on('publicMsgReceived', res=>{this.msgs.push(res)});//开始连接this.connection.start();},
JwtItem(){this.startConnection();//调用startConnection方法},
//调用后端方法
sendMessage() {//传递数据this.connection.invoke('SendPublicMsg', this.sigtext)
}
启动连接,我们可以看到JWT令牌通过url中的QueryString传递。