JWT指定了一种生成字符串的规则,使用JWT生成字符信息,包含用户信息
客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。
此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。当跨域时,也可以将JWT被放置于POST请求的数据主体中。
在commom_utils模块pom中添加jwt工具依赖
<dependencies>
<!-- JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
public class JwtUtils {
public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //密钥,每个公司按照自己的规则生成,后面做加密
public static String getJwtToken(String id, String nickname){
String JwtToken = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.setSubject("guli-user")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.claim("id", id)
.claim("nickname", nickname)
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
return JwtToken;
}
/**
* 判断token是否存在与有效
* @param jwtToken
* @return
*/
public static boolean checkToken(String jwtToken) {
if(StringUtils.isEmpty(jwtToken)) return false;
try {
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断token是否存在与有效
* @param request
* @return
*/
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return false;
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据token获取会员id
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
Claims claims = claimsJws.getBody();
return (String)claims.get("id");
}
}
@Data
@ApiModel(value="登录对象", description="登录对象")
public class LoginVo {
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "密码")
private String password;
}
MemberApiController
@RestController
@RequestMapping("/ucenterservice/apimember")
@CrossOrigin
public class MemberApiController {
@Autowired
private MemberService memberService;
@ApiOperation(value = "会员登录")
@PostMapping("login")
public R login(@RequestBody LoginVo loginVo) {
String token = memberService.login(loginVo);
return R.ok().data("token", token);
}
}
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
/**
* 会员登录
* @param loginVo
* @return
*/
@Override
public String login(LoginVo loginVo) {
String mobile = loginVo.getMobile();
String password = loginVo.getPassword();
//校验参数
if(StringUtils.isEmpty(mobile) ||
StringUtils.isEmpty(password) ||
StringUtils.isEmpty(mobile)) {
throw new GuliException(20001,"error");
}
//获取会员
Member member = baseMapper.selectOne(new QueryWrapper<Member>().eq("mobile", mobile));
if(null == member) {
throw new GuliException(20001,"error");
}
//校验密码
if(!MD5.encrypt(password).equals(member.getPassword())) {
throw new GuliException(20001,"error");
}
//校验是否被禁用
if(member.getIsDisabled()) {
throw new GuliException(20001,"error");
}
//使用JWT生成token字符串
String token = JwtUtils.getJwtToken(member.getId(), member.getNickname());
return token;
}
}
@Data
@ApiModel(value="注册对象", description="注册对象")
public class RegisterVo {
@ApiModelProperty(value = "昵称")
private String nickname;
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "验证码")
private String code;
}
MemberApiController调用方法
@RestController
@RequestMapping("/ucenterservice/apimember")
@CrossOrigin
public class MemberApiController {
@Autowired
private MemberService memberService;
@ApiOperation(value = "会员登录")
@PostMapping("login")
public R login(@RequestBody LoginVo loginVo) {
String token = memberService.login(loginVo);
return R.ok().data("token", token);
}
@ApiOperation(value = "会员注册")
@PostMapping("register")
public R register(@RequestBody RegisterVo registerVo){
memberService.register(registerVo);
return R.ok();
}
}
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 会员注册
* @param registerVo
*/
@Override
public void register(RegisterVo registerVo) {
//获取注册信息,进行校验
String nickname = registerVo.getNickname();
String mobile = registerVo.getMobile();
String password = registerVo.getPassword();
String code = registerVo.getCode();
//校验参数
if(StringUtils.isEmpty(mobile) ||
StringUtils.isEmpty(mobile) ||
StringUtils.isEmpty(password) ||
StringUtils.isEmpty(code)) {
throw new GuliException(20001,"error");
}
//校验校验验证码
//从redis获取发送的验证码
String mobleCode = redisTemplate.opsForValue().get(mobile);
if(!code.equals(mobleCode)) {
throw new GuliException(20001,"error");
}
//查询数据库中是否存在相同的手机号码
Integer count = baseMapper.selectCount(new QueryWrapper<Member>().eq("mobile", mobile));
if(count.intValue() > 0) {
throw new GuliException(20001,"error");
}
//添加注册信息到数据库
Member member = new Member();
member.setNickname(nickname);
member.setMobile(registerVo.getMobile());
member.setPassword(MD5.encrypt(password));
member.setIsDisabled(false);
member.setAvatar("http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132");
this.save(member);
}
}
为了前台页面显示用户信息,JWT生成时存了用户的id和昵称信息,用户登陆后可以通过Cookie或路径url等方式将JWT传到前端页面中去,前端需要显示用户的昵称和头像等信息,所以需要从JWT种获取用户信息展示到前端
@ApiOperation(value = "根据token获取登录信息")
@GetMapping("auth/getLoginInfo")
public R getLoginInfo(HttpServletRequest request){
try {
String memberId = JwtUtils.getMemberIdByJwtToken(request);
LoginInfoVo loginInfoVo = memberService.getLoginInfo(memberId);
return R.ok().data("item", loginInfoVo);
}catch (Exception e){
e.printStackTrace();
throw new GuliException(20001,"error");
}
}
//根据JWT的id信息获取用户信息
@Override
public LoginInfoVo getLoginInfo(String memberId) {
Member member = baseMapper.selectById(memberId);
LoginInfoVo loginInfoVo = new LoginInfoVo();
BeanUtils.copyProperties(member, loginInfoVo);
return loginInfoVo;
}