Java 手机Web开发 身份验证

Java web和手机端开发 遇到比较麻烦的就是身份验证

目前为止觉得最好的解决方案是 Java 中使用jwt 

为什么要使用jwt,让网络数据更加安全,以防其他一些人无意恶搞
在这里简单说下:jwt是一个开源的java库,一个自包含的Java库,提供终端到终端的JSON网络令牌的创建和验证。
JWT的目标是成为最简单的库,用于创建和JVM上的验证JSON网络令牌(JWTs),

这里采用的框架是nutz框架 数据库mysql  和redis

Jwts 验证需要一个key 但是 KEY默认是存储在内存 如果想长久存储 使用redis以字节流方式 更好

其次 token的获取用redis 更加方便 存储时加一个过期时间 不占用资源


直接看代码

@IocBean(args = {"refer:dao"})
public class ApiService extends Service {
    private static final Log log = Logs.get();

    public ApiService(Dao dao) {
        super(dao);
    }

    private static final String at="accessToken";

    public static Key key;

    /**
     * 生成token
     * Key以字节流形式存入redis
     *
     * @param date  失效时间
     * @param appId AppId
     * @return
     */
    @Aop("redis")
    public String generateToken(Date date, String appId){
        try{
            byte[] buf = jedis().get("api:key".getBytes());
            if (buf == null) { // 建新的key
                key = MacProvider.generateKey();
                ByteArrayOutputStream bao = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bao);
                oos.writeObject(key);
                buf = bao.toByteArray();
                jedis().set("api:key".getBytes(), buf);
            } else { // 重用老key
                key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();
            }
        }catch (IOException io){
            System.out.println(io);
        }catch (ClassNotFoundException c){
            System.out.println(c);
        }
        String token = Jwts.builder()
                .setSubject(appId)
                .signWith(SignatureAlgorithm.HS512, key)
                .setExpiration(date)
                .compact();
        // 计算失效秒,7889400秒三个月
        Date temp = new Date();
        long interval = (date.getTime() - temp.getTime())/1000;
        jedis().setex(at+appId ,(int)interval,token);
        return token;
    }

    /**
     * 验证token
     * @param appId AppId
     * @param token token
     * @return
     */
    @Aop("redis")
    public boolean verifyToken(String appId, String token) {
        try {
            if (key == null) {
                byte[] buf = jedis().get("api:key".getBytes());
                if(buf==null){
                    return false;
                }
                key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();
            }
            Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody().getSubject().equals(appId);
            return true;
        } catch (Exception e) {
            log.debug(e.getMessage());
            return false;
        }
    }

    /**
     * 获取token
     * @param appId
     * @return
     */
    @Aop("redis")
    public String getToken(String appId) {

        return jedis().get(at+appId);
    }

    /**
     * 验证会员ID,用于首页接口、产品查看、收藏等接口
     * @param appId
     * @return
     */
    public boolean verifyId(String appId) {
        try {
            App_user user = dao().fetch(App_user.class, Cnd.where("id","=",Long.parseLong(appId)));
            if (user!=null){
                return true;
            }else {
                return false;
            }
        } catch (Exception e) {
            log.debug(e.getMessage());
            return false;
        }
    }

如果不想用redis存储可以采用文件流的形式

参考代码如下

github地址https://github.com/Wizzercn/NutzWk/blob/7851cfdb8688b30d5843d6a162113cd1d033ccc9/src/main/java/cn/wizzer/modules/services/sys/SysApiService.java#L65

package cn.wizzer.modules.services.sys;

import cn.wizzer.common.base.Globals;
import cn.wizzer.common.base.Result;
import cn.wizzer.common.base.Service;
import cn.wizzer.modules.models.sys.Sys_api;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Files;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.io.*;
import java.security.Key;
import java.util.Date;

/**
 * Created by wizzer on 2016/8/11.
 */
@IocBean(args = {"refer:dao"})
public class SysApiService extends Service {
    private static final Log log = Logs.get();

    public SysApiService(Dao dao) {
        super(dao);
    }

    public static Key key;

    /**
     * 生成token
     *
     * @param date 失效时间
     * @param appId  appId
     * @return
     */
    public String generateToken(Date date, String appId) throws IOException, ClassNotFoundException {
        File f = new File(Globals.AppRoot + "/WEB-INF/apikey/" + appId + ".key");
        if (Files.isFile(f)) {
            ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(f));
            key = (Key) keyIn.readObject();
            keyIn.close();
        } else {
            key = MacProvider.generateKey();
            Files.createNewFile(f);
            ObjectOutputStream keyOut = new ObjectOutputStream(new FileOutputStream(f));
            keyOut.writeObject(key);
            keyOut.close();
        }

        return Jwts.builder()
                .setSubject(appId)
                .signWith(SignatureAlgorithm.HS512, key)
                .setExpiration(date)
                .compact();
    }

    /**
     * 验证token
     *
     * @param appId AppId
     * @param token token
     * @return
     */
    public boolean verifyToken(String appId, String token) {
        try {
            if (key == null) {
                ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(Globals.AppRoot + "/WEB-INF/apikey/" + appId + ".key"));
                key = (Key) keyIn.readObject();
                keyIn.close();
            }
            Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody().getSubject().equals(appId);
            return true;
        } catch (Exception e) {
            log.debug(e.getMessage());
            return false;
        }
    }
}


你可能感兴趣的:(nutz)