AntDesign Pro + .NET Core 实现基于JWT的登录认证

修改ASP.NET Core后端代码
“JwtSetting”: {
“SecurityKey”: “xxxxxxxxxxxx”, // 密钥
“Issuer”: “agileconfig.admin”, // 颁发者
“Audience”: “agileconfig.admin”, // 接收者
“ExpireSeconds”: 20 // 过期时间 s
}
在appsettings.json文件添加jwt相关配置。

public class JwtSetting
{
static JwtSetting()
{
Instance = new JwtSetting();
Instance.Audience = Global.Config[“JwtSetting:Audience”];
Instance.SecurityKey = Global.Config[“JwtSetting:SecurityKey”];
Instance.Issuer = Global.Config[“JwtSetting:Issuer”];
Instance.ExpireSeconds = int.Parse(Global.Config[“JwtSetting:ExpireSeconds”]);
}

    public string SecurityKey { get; set; }

    public string Issuer { get; set; }

    public string Audience { get; set; }

    public int ExpireSeconds { get; set; }

    public static JwtSetting Instance
    {
        get;
    }
}

定义一个JwtSetting类,用来读取配置。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                  .AddJwtBearer(options =>
                  {
                      options.TokenValidationParameters = new TokenValidationParameters
                      {
                          ValidIssuer = JwtSetting.Instance.Issuer,
                          ValidAudience = JwtSetting.Instance.Audience,
                          IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSetting.Instance.SecurityKey)),
                      };
                  });
        services.AddCors();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddRazorRuntimeCompilation();
        services.AddFreeSqlDbContext();
        services.AddBusinessServices();
        services.AddAntiforgery(o => o.SuppressXFrameOptionsHeader = true);
    }

修改Startup文件的ConfigureServices方法,修改认证Scheme为JwtBearerDefaults.AuthenticationScheme,在AddJwtBearer方法内配置jwt相关配置信息。因为前后端分离项目所以有可能api跟ui部署在不同的域名下,所以开启Cors。

 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseMiddleware<ExceptionHandlerMiddleware>();
        }
        app.UseCors(op=> {
            op.AllowAnyOrigin();
            op.AllowAnyMethod();
            op.AllowAnyHeader();
        });
        app.UseWebSockets(new WebSocketOptions()
        {
            KeepAliveInterval = TimeSpan.FromSeconds(60),
            ReceiveBufferSize = 2 * 1024
        });
        app.UseMiddleware<WebsocketHandlerMiddleware>();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }

修改Startup的Configure方法,配置Cors为Any。

public class JWT
{
    public static string GetToken()
    {
        //创建用户身份标识,可按需要添加更多信息
        var claims = new Claim[]
        {
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("id", "admin", ClaimValueTypes.String), // 用户id
new Claim("name", "admin"), // 用户名
new Claim("admin", true.ToString() ,ClaimValueTypes.Boolean) // 是否是管理员
        };
        var key = Encoding.UTF8.GetBytes(JwtSetting.Instance.SecurityKey);
        //创建令牌
        var token = new JwtSecurityToken(
          issuer: JwtSetting.Instance.Issuer,
          audience: JwtSetting.Instance.Audience,
          signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
          claims: claims,
          notBefore: DateTime.Now,
          expires: DateTime.Now.AddSeconds(JwtSetting.Instance.ExpireSeconds)
        );

        string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

        return jwtToken;
    }
}

添加一个JWT静态类用来生成jwt的token。因为agileconfig的用户只有admin一个所以这里用户名,ID都直接写死。

[HttpPost(“admin/jwt/login”)]
public async Task Login4AntdPro([FromBody] LoginVM model)
{
string password = model.password;
if (string.IsNullOrEmpty(password))
{
return Json(new
{
status = “error”,
message = “密码不能为空”
});
}

        var result = await _settingService.ValidateAdminPassword(password);
        if (result)
        {

            var jwt = JWT.GetToken();

            return Json(new { 
                status="ok",
                token=jwt,
                type= "Bearer",
                currentAuthority = "admin"
            });
        }

        return Json(new
        {
            status = "error",
            message = "密码错误"
        });
    }

新增一个Action方法做为登录的入口。在这里验证完密码后生成token,并且返回到前端。
到这里.net core这边后端代码改动的差不多了。主要是添加jwt相关的东西,这些内容网上已经写了很多了,不在赘述。
下面开始修改前端代码。

修改AntDesign Pro的代码
AntDesign Pro已经为我们生成好了登录页面,登录的逻辑等,但是原来的登录是假的,也不支持jwt token做为登录凭证,下面我们要修改多个文件来完善这个登录。

export function setToken(token:string): void {
localStorage.setItem(‘token’, token);
}

export function getToken(): string {
var tk = localStorage.getItem(‘token’);
if (tk) {
return tk as string;
}

return ‘’;
}

在utils/authority.ts文件内新增2个方法,用来存储跟获取token。我们的jwt token存储在localStorage里。

/** 配置request请求时的默认参数 */
const request = extend({
prefix: ‘http://localhost:5000’,
errorHandler, // 默认错误处理
credentials: ‘same-origin’, // 默认请求是否带上cookie,
});
const authHeaderInterceptor = (url: string, options: RequestOptionsInit) => {
const authHeader = { Authorization: 'Bearer ’ + getToken() };
return {
url: ${url},
options: { …options, interceptors: true, headers: authHeader },
};
};

request.interceptors.request.use(authHeaderInterceptor);
修改utils/request.ts文件,定义一个添加Authorization头部的拦截器,并且使用这个拦截器,这有每次请求的时候自动会带上这个头部,把jwt token传送到后台。
设置prefix为http://localhost:5000这是我们的后端api的服务地址,真正生产的时候会替换为正式地址。
设置credentials为same-origin。

export async function accountLogin(params: LoginParamsType) {
return request(’/admin/jwt/login’, {
method: ‘POST’,
data: params,
});
}

在services/login.ts文件内新增发起登录请求的方法。

effects: {
login({ payload }, { call, put }) {
const response = yield call(accountLogin, payload);
yield put({
type: ‘changeLoginStatus’,
payload: response,
});
// Login successfully
if (response.status === ‘ok’) {
const urlParams = new URL(window.location.href);
const params = getPageQuery();
message.success(‘🎉 🎉 🎉 登录成功!’);
let { redirect } = params as { redirect: string };
if (redirect) {
console.log('redirect url ’ , redirect);
const redirectUrlParams = new URL(redirect);
if (redirectUrlParams.origin === urlParams.origin) {
redirect = redirect.substr(urlParams.origin.length);
if (redirect.match(/^/.
#/)) {
redirect = redirect.substr(redirect.indexOf(’#’) + 1);
}
} else {
window.location.href = ‘/’;
return;
}
}
history.replace(redirect || ‘/’);
}
},

 reducers: {
changeLoginStatus(state, { payload }) {
  setAuthority(payload.currentAuthority);
  setToken(payload.token)
  return {
    ...state,
    status: payload.status,
    type: payload.type,
  };
},

},
修改models/login.ts文件,修改effects的login方法,在内部替换原来的fakeAccountLogin为accountLogin。同时修改reducers内部的changeLoginStatus方法,添加setToken的代码,这有修改后登录成功后token就会被存储起来。

effects: {
*fetch(, { call, put }) {
const response = yield call(queryUsers);
yield put({
type: ‘save’,
payload: response,
});
},
*fetchCurrent(
, { call, put }) {
const response = {
name: ‘管理员’,
userid: ‘admin’
};
yield put({
type: ‘saveCurrentUser’,
payload: response,
});
},
},
修改models/user.ts文件,修改effects的fetchCurrent方法为直接返回response。本来fetchCurrent是会去后台拉当前用户信息的,因为agileconfig的用户就admin一个,所以我直接写死了。
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值