需要提供两个接口,用户认证接口和访问前检验token接口。
流程:
- 用户传入username和password(以“zhangsan" "123456"为例),拿着这两个信息去查数据库作认证。若认证通过,基于想要的用户信息生成一个token,然后把token响应给用户。
- 日后用户在请求其他接口的时候,用户都要携带着token请求。若携带的token验证通过,则服务器允许访问;若验证不通过,则服务器拒绝访问。
一、配置pom.xml
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
二、配置application.properties文件
配置数据库和mybatis
三、建立数据库和数据库中的表
表结构:
表中数据:
四、实体
包:entity
实体类:UserAdmin
@TableName("user")
public class UserAdmin {
private String id;
private String name;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
五、DAO接口和mapper.xml
包:java下面的mapper
DAO接口:UserAdminMapper
@Mapper
public interface UserAdminMapper{
UserAdmin login(UserAdmin userAdmin);
}
包:resources下面的mapper
UserAdminMapper.xml文件
<mapper namespace="com.xxx.gamejump.mapper.UserAdminMapper">
<select id="login" parameterType="UserAdmin" resultType="UserAdmin">
select * from g_admin where name =#{name} and password =#{password}
</select>
</mapper>
六、Service接口以及实现类
@Service
public interface UserAdminService {
/*
管理员登录接口
*/
UserAdmin login(UserAdmin userAdmin);
}
@Service
@Transactional
public class UserAdminServiceImpl implements UserAdminService{
@Autowired
private UserAdminMapper userAdminMapper;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public UserAdmin login(UserAdmin userAdmin) {
//根据接收的用户名和密码查询数据库
UserAdmin admin = userAdminMapper.login(userAdmin);
if(admin != null){
return admin;
}
throw new RuntimeException("登陆失败--");
}
}
七、Controller类
UserAdminController类
login方法:验证用户名密码,生成token令牌
@RestController
@RequestMapping("/admin")
@CrossOrigin(origins = "*")
public class UserAdminController {
private Logger logger = LoggerFactory.getLogger(UserAdminController.class);
@Autowired
private UserAdminService userAdminService;
@GetMapping("/login")
public Map<String,Object> login(UserAdmin userAdmin){
logger.info("用户名:[{}]",userAdmin.getName());
logger.info("密码:[{}]",userAdmin.getPassword());
Map<String,Object> map = new HashMap<>();
try{
UserAdmin useradminDB = userAdminService.login(userAdmin);
Map<String,String> payload = new HashMap<>();
payload.put("id",useradminDB.getId());
payload.put("name",useradminDB.getName());
//生成JWT令牌
String token = JWTUtils.getToken(payload);
map.put("state",true);
map.put("msg","认证成功");
map.put("token",token);//响应token
}catch(Exception e){
map.put("state",false);
map.put("msg",e.getMessage());
}
return map;
}
首先运行程序,然后用Postman工具测试login方法。
测试1:认证成功示例
GET方式访问:http://localhost:8089/admin/login?name=lrq&password=12345
传参:
name:lrq
password:12345
因为数据库表中有一行为这组数据,所以成功查询数据库表,用户名密码验证成功。
服务器响应如下:
服务器端:
postman客户端:
测试2:认证失败示例
GET方式访问:http://localhost:8089/admin/login?name=xiaoming&password=12345
传参:
name:xiaoming
password:12345
数据库中没有xiaoming这行数据,用户名密码验证失败。
服务器响应如下:
服务器端:
postman客户端:
test方法:进入任意接口之前都要进行的jwt检验方法
@PostMapping("/test")
public Map<String,Object> test(String token) {
Map<String, Object> map = new HashMap<>();
logger.info("当前token为:[{}]", token);
//System.out.println("当前token为");
try {
DecodedJWT verify = JWTUtils.verify(token); //验证令牌
map.put("state",true);
map.put("msg","请求成功!");
return map;
} catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msg","无效签名!");
} catch (TokenExpiredException e) {
e.printStackTrace();
map.put("msg","token过期!");
} catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg","算法不一致!");
} catch (Exception e) {
e.printStackTrace();
map.put("msg","token无效!");
}
map.put("state",false);
return map;
}
测试1:不传入token
服务器端:
postman客户端:
测试2: 传入合法token
Postman客户端:
服务器端:
注:POST方式请求时的token传参,官方不建议在url中以参数形式传递token,建议将token隐藏放置在请求头里面。
测试3:token过期
Postman客户端:
服务器端: