后端006_登录之后返回Token
现在开始我们就可以写登录相关的东西了。首先登录相关的流程是这样的,前端输入用户和密码传给后端,后端判断用户名和密码是否正确,若正确,则生成JWT令牌,若不正确,则需要让前端重新输入,前端如果拿到了JWT令牌,则会将令牌放在请求头里面,后面的每一次请求都会携带这个JWT令牌。然后,我们会写一个JWT相关的令牌拦截器。每次请求之前,先走一遍拦截器,判断一下当前的令牌是否存在,和令牌是否正确合法有效。若不存在或者并不是合法有效的,我们肯定会进行拦截,不会让其访问其他的接口,若合法,则让其访问接口。
我们现在实现第一个接口。前端传用户名和密码。我们根据传入的值判断是否正确,正确则生成JWT令牌。
首先我们在Pojo下面的Admin类下,让其集成UserDetails这个类。也可以专门写一个类去实现UserDetails,因为我们现在是springsecurity框架,该框架里面真正登录的方法是使用UserDetailsService类里面的一个方法LoginUserByUserName()。登录之后返回的就是UserDetails。
然后在实现UserDetailsService类时,要重写几个方法。
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
} @Override
public boolean isAccountNonExpired() {
return true;
} @Override
public boolean isAccountNonLocked() {
return true;
} @Override
public boolean isCredentialsNonExpired() {
return true;
} @Override
public boolean isEnabled() {
return enabled;
}
这里要把IsAccountNonExpired(),isAccountNonLocked(),isCredentialsNoExpired()的返回值改成true,否则会登录失败。把getAuthorities()方法的返回值改成Null.这里是关于权限的,先空着。对于isEnabled()方法。因为admin类中已经有了enabled的属性了,所以直接返回enabled就可以了。
这时,我们在pojo中还要再新建一个类,AdminLoginParam用户登录实体类,这个类专门用来传递前端传过来的用户名和密码。这里我们无需使用admin类,因为登录只需要传递用户名和密码就可以。
实现添加lombook的三个注解,@Data,@EqualsAndHashCode,@Accessors(chain = true)
然后再添加Swgger的注解 @ApiModel(value="AdminLogin对象",description="")
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; /**
* @Author: zhougang
* @Date: 2021/11/9
* @Time: 19:26
* @Description:用户登录实例类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "AdminLogin对象",description = "")
public class AdminLoginParam {
@ApiModelProperty(value = "用户名",required = true)
private String username;
@ApiModelProperty(value = "密码",required = true)
private String password; }
这里有2个属性,用户名和密码,在上面添加了@ApiModelProperty注解。
上述类建造完成。
这时候我们就开始进行我们的登录功能。可以选择先写Controller再写Service,再写Mapper,也可以选择从后面往前面写,都可以。我们这里先从前面王后面写。
首先我们在controller中新建一个LoginController。加上@RestController注解,然后加上swagger注解@Api(tags = "LoginController")
后面我们就不再用注释直接使用swagger作为注释了。
@Api(tags = "LoginController")
@RestController
public class LoginController {
@Autowired
private IAdminService adminService; @ApiOperation(value="登录之后返回token")
@PostMapping("/login")
public RespBean login(AdminLoginParam adminLoginParam, HttpServletRequest request) {
return adminService.login(adminLoginParam.getUsername(), adminLoginParam.getPassword(), request);
}
}
这样上述的controller就已经写完了,然后我们去写上述方法中调用的login接口。
public interface IAdminService extends IService<Admin> {
/**
* 登录之后返回token
* @param username
* @param password
* @param request
* @return
*/
RespBean login(String username, String password, HttpServletRequest request);
}
写完上面的接口之后,我们要撰写其实现类AdminServiceImpl,使用springsecurity中的userdetails类中的loaduserbyusername实现登录
1.因为要使用到UserDetails所以我们需要先注入 UserDetailsService
2.使用UserDetailsService中的LoadUserByUsername()方法获取UserDetails
3.判断当前获取的到UserDetails是否存在,然后注入PasswordEncoder。使用PasswordEncoder类的maches方法将 前端传入的password和userDetails.getPassword()进行匹配。
@Override
public RespBean login(String username, String password, HttpServletRequest request) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (null == userDetails || !passwordEncoder.matches(password, userDetails.getPassword())) {
return RespBean.error("用户名或密码不正确");
}
使用UserDetail中的isEnabled还可以判断账号是否禁用。
if (userDetails.isEnabled()){
return RespBean.error("账号被禁用,请联系管理员");
}
若上述的判断都没问题,就可以判断已经登录成功了, 首选注入JwtTokenUtil
@Autowired
private JwtTokenUtil jwtTokenUtil;
生成token
//生成token
String token = jwtTokenUtil.generateToken(userDetails);
然后新建一个tokenMap集合。在集合中放入Token值,Tokenhead。其中TokenHead通过@value注解注入,然后我们使用RespBean把登录成功的信息返回出去。
@Value("${jwt.tokenHead}")
private String tokenHead;
//生成token
String token = jwtTokenUtil.generateToken(userDetails);
Map<String, String> tokenmap = new HashMap<>();
tokenmap.put("token",token);
tokenmap.put("tokenHead",tokenHead);
return RespBean.sucess("登录成功",tokenmap);
还有地方需要注意一下,登录成功之后,如果我们还需要拿到登录用户的信息,可以使用spring security中的某些对象,例如UserDetails。既然要获取这个对象,当我们登录成功之后,我们要把我们登录的这个对象放在springsecurity的全文中,那下次拿到的这个对象就是我们已经登录过的对象。如果没有放,则可能会出现问题。
我们使用 UsernamePasswordAuthenticationToken这个类,创建对象,第一个参数是userDetails。第二个参数是所谓的凭证,也可以看做是密码。一般置为空,第三个参数就是权限的列表。这样我们就拿到了一个token。有了token之后,我们可以把这个token放在springsecurity的全局里面,具体要怎么放呢,可以使用其getContext()方法,然后调用setAuthentication()方法,参数就是我们获取的token值,这样就可以更新对象了。
/**
* 在登录成功之后,后期再去获取响应的用户信息的时候,可以使用
* spring安全框架提供的一些对象。我们需要把登录的用户对象放在spring
* 安全框架的全文中。下次使用该对象就是我们当前登录用户的对象。
* 否者会发生问题
*/
//更新security登录用户的对象
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
//将获取的authenticationToken放置在全局中
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
在上面我们引入了PasswordEncoder对象,目前还是爆红状态,现在先不管,后面运行的时候再设置。
后端006_登录之后返回Token的更多相关文章
- 用户登录并返回token(springboot)
何为token?[如果想直接看代码可以往下翻] 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的:1. 客户端使用用户名跟密码请求登录2. 服务端收到请求,去 ...
- 七:Spring Security 前后端分离登录,非法请求直接返回 JSON
Spring Security 前后端分离登录,非法请求直接返回 JSON 解决方案 在 Spring Security 中未获认证的请求默认会重定向到登录页,但是在前后端分离的登录中,这个默认行为则 ...
- Laravel5.5+ 区分前后端用户登录
Laravel 的用户认证是通过 Auth Facade 门脸实现的,手动认证可是使用 Auth::login() 或 Auth::attempt() 这两个方法实现. 以下内容纯属个人实现,也许有 ...
- python接口自动化: CAS系统验证,自动完成登录并获取token,遇到302请求重定向设置(requests模块 allow_redirects=False)即可
import requestsimport re import requests import re class Crm_token(object): try: username=int(input( ...
- php弹出式登录窗口并获得登录后返回值
一款bootstrap样式结合php制作的弹出式登录窗口,输入用户名和密码后,ajax传参给后台,并获得登录后返回值. hwLayer+ajax弹出登录框 $(function() { $('#for ...
- SpringSecurity兑现多登录成功页面和登录成功返回被拦截界面
SpringSecurity实现多登录成功页面和登录成功返回被拦截界面 使用SrpingSceurity作为认证和授权的安全框架可以省下很多基础工作. 具体可以参考SpringSecurity,这里不 ...
- Spring Security 前后端分离登录,非法请求直接返回 JSON
hello 各位小伙伴,国庆节终于过完啦,松哥也回来啦,今天开始咱们继续发干货! 关于 Spring Security,松哥之前发过多篇文章和大家聊聊这个安全框架的使用: 手把手带你入门 Spring ...
- MOOC(9)- 登录接口返回的cookie中有多个token
- beego 前后端分离登录验证
conf>app.conf 文件添加一下参数 copyrequestbody=true sessionon =true routers>router.go 文件添加初始化路由 func i ...
- odoo11登录之后返回的session信息分析
{ "id": null, "jsonrpc": "2.0", "result": { "web_tours& ...
随机推荐
- 【C学习笔记】day1-1 打印100~200之间的素数
#include<stdio.h> int sushu(int input) { int m = 0; for (int i = 1; i <= input; i++) { if ( ...
- window 画工业图软件
1.autoCAD 2.visio 3.CorelDraw 4.DrawIO
- Java基础——(综合练习)选手打分
package com.zhao.test; import java.util.Scanner; public class Test17 { /* 需求 : 在唱歌比赛中,有6名评委给选手打分,分数范 ...
- locust socektio协议压测
# -*-coding:UTF-8 -*- from locust import HttpLocust, TaskSet, task, TaskSequence, Locust, events imp ...
- 计蒜客(Stone Game)01背包
题意:在集合中挑一些数,形成一个集合S,剩下的数形成另一个集合P,使得S>= P ,并且对于S中任意元素ai,S-ai<=P 问有多少种方案. 题目链接:https://nanti.jis ...
- C语言ll一作业01
1. 作业头 | 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/zswxy/SE2020-3 | | ---- | ---- | ---- | | 这个作业目 ...
- Docker基本命令之 仓库管理(docker hub)
仓库管理 仓库介绍:仓库(Repository)就是集中存放镜像的地方 登录docker hub注册一个自己的账号 然后创建一个仓库:xxx 登录:docker login -- 输入用户名/密码(退 ...
- #AI 绘图 #GitHub GitHub上这几个项目教你怎么用,让你成为神笔马良
1.前情提要 前两天在 GitHub Trending 上看到个利用 AI 自动给图片上色的项目(style2paints)火起来了. 在 AI 大行其道的时代,工程师们也开始思考如何用这项技术来解决 ...
- Java 中的内存分配
Java 中的内存分配 Java 程序运行时,需要在内存中分配空间.为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式. 一.栈:储存局部变量 局部变量 ...
- OO课程第三阶段(实验和pta试题)总结Blog3
OO课程第三阶段(实验和pta试题)总结Blog3 前言:学习OOP课程的第三阶段已经结束了,在此进行对于知识点,题量,难度的个人看法. 学习OOP课程的第三阶段已经结束了,较第一次阶段学习难度加大, ...