使用Jwt令牌做单点登陆
使用Springboot搭建后台,集成JWT令牌,作为token
- 导入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
- 配置文件
jwt: #jwt配置,提供个JwtUtils类去使用
key: kaikai_ty #jwt生成token时的密钥
expiration: 1500000 #token的过期时间 1500毫秒
- 起步引导类配置
@SpringBootApplication
@ServletComponentScan(basePackages="") //filter过滤器的包路径
public class application{
public static void main(String[] args){
SpringApplication.run(application.class,args);
}
//将该工具类被放到bean中
@Bean
public JwtUtils jwt(){
return new JwtUtils;
}
}
- jwtUtils配置类
该类主要用于生成和解析Jwt令牌的
//token工具类
@ConfigurationProperties(prefix = "jwt") //加载application.yml配置文件jwt节点的信息
public class JWTUtil {
private String key; //密钥,名称要与application.yml中配的一样
private long expiration; //过期时间,名称要与application.yml中配的一样
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getExpiration() {
return expiration;
}
public void setExpiration(long expiration) {
this.expiration = expiration;
}
//生成token
public String getToken(String userNo, String password) {
long curTime = System.currentTimeMillis();
JwtBuilder builder = Jwts.builder()
.setId(userNo).setSubject(password) //使用用户账号和密码
.setIssuedAt(new Date(curTime)) //设置token创建时间
.signWith(SignatureAlgorithm.HS256, key); //进行签名,HS256方式,密钥为key
if (expiration > 0) {
builder.setExpiration(new Date(curTime + expiration)); //设置token过期时间
}
//builder.claim("key1", "value1"); ?//添加自定义key:value对
return builder.compact(); //生成token
}
//解析token
public Claims parser(String token) {
Claims c = Jwts.parser().setSigningKey(key) .parseClaimsJws(token).getBody(); //解析token
return c;
}
}
- 配置拦截器
@Configuration //配置类注解
public class loginFilterConfig extends WebMvcConfigurationSupport {
@Autowired
private loginFilterJwt loginFilter;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginFilter) //加入自定义的拦截器类
.addPathPatterns("/**") //拦截所有接口
.excludePathPatterns("/userController/login"); //对登录接口放行
}
}
- 配置过滤器filter
@Component
@PropertySource({"classpath:url.properties"}) //配置文件中的url路径
public class loginFilterJwt extends HandlerInterceptorAdapter { //登录拦截器
@Autowired
private JWTUtil jWTUtil;
//访问所有接口时,进行拦截
@Autowired
private userDao userDaod; //调用数据库,根据解析的jwt令牌去查询数据库
@Value("${url.login}")
private String url;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authHead = request.getHeader("Authorization");
authHead="Bearer "+authHead;
if (authHead == null || authHead.trim().equals("") || !authHead.startsWith("Bearer ")) {
response.sendRedirect(url);
return false; //没有登录
}
String token = authHead.substring(7);
try {
Claims c = jWTUtil.parser(token); //调用JWTUtil工具类解析token
String userNo = c.getId();
String userName = userDaod.findUserName(userNo);//通过解析到的用户名去查询数据库
if (userName == null || userName.trim().equals("")) {
response.sendRedirect(url);
return false; //非法登录
}
} catch (Exception e) {//token过期时会报错
e.printStackTrace();
response.sendRedirect(url);
return false; //登录超时
}
return true; //已登录,让通过,访问实际接口
}
}
- 登陆代码
@postMapping("login")
public AjaxRsult login(@RequestParam(value="userName")String userName,@RequestParame(value="password")String password){
UserInfo userinfo = userService.login(userName,password)//调用service层,查询数据库,如果数据库有对应的数据,返回的实体类有值
if(userinfo!=null){
String jwtToken = jwtUtils.getToken(userName,password);
//我们可以将token放到cookie中返回给前端,或者直接以json的形式返回
return new Ajaxresult(true,"登陆成功",jwtToken,100);
}
}
我们也可以将token 存储到数据库,然后当用户登陆的时候去查询数据库是否有对应的数据,再做判断,但是这里设置有的效期不到半小时,没必要去操作一次数据库,或者我们可以将token存储到session中,然后用访问其他页面再去session中取tokn也可以,但session会增大服务器的压力,建议还是直接根据解析的token的数据,然后查询数据库