SpringBoot 基于jjwt快速实现token授权
1、添加maven依赖注解
       <!--JJWT库-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>
2、添加登录获取token时,所需要的认证信息类LoginPara.Java
/**
 * 添加登录获取token时,所需要的认证信息类LoginPara.Java
 * Created by CatalpaFlat on 2017/8/29.
 */
public class LoginPara {
    private String clientId;
    private String userName;
    private String password;
    public String getClientId() {
        return clientId;
    }
    public void setClientId(String clientId) {
        this.clientId = clientId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
3、添加token返回结果类AccessToken.java
/**
 * 添加token返回结果类AccessToken.java
 * Created by CatalpaFlat on 2017/8/29.
 */
public class AccessToken {
    private String access_token;
    private String token_type;
    private long expires_in;
    public String getAccess_token() {
        return access_token;
    }
    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }
    public String getToken_type() {
        return token_type;
    }
    public void setToken_type(String token_type) {
        this.token_type = token_type;
    }
    public long getExpires_in() {
        return expires_in;
    }
    public void setExpires_in(long expires_in) {
        this.expires_in = expires_in;
    }
}
4、添加用于拼装token认证TokenObject类
/**
 * Created by CatalpaFlat on 2017/8/31.
 */
@Component
public class TokenObject {
    /**客户端id*/
    private String clientId;
    /**base64加密*/
    private String base64Secret;
    /**用户名*/
    private String name;
    /**到期时间*/
    private long expiresSecond;
    /**管理员名称*/
    private String userName;
    /**管理员id*/
    private Integer aId;
    /**职能*/
    private String role;
    /**项目名称*/
    private String project;
    public String getProject() {
        return project;
    }
    public void setProject(String project) {
        this.project = project;
    }
    public String getClientId() {
        return clientId;
    }
    public void setClientId(String clientId) {
        this.clientId = clientId;
    }
    public String getBase64Secret() {
        return base64Secret;
    }
    public void setBase64Secret(String base64Secret) {
        this.base64Secret = base64Secret;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public long getExpiresSecond() {
        return expiresSecond;
    }
    public void setExpiresSecond(long expiresSecond) {
        this.expiresSecond = expiresSecond;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Integer getaId() {
        return aId;
    }
    public void setaId(Integer aId) {
        this.aId = aId;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
}
5、添加构造jwt及解析jwt的帮助类JwtHelper.java
/**
 * 添加构造jwt及解析jwt的帮助类JwtHelper.java
 * Created by CatalpaFlat on 2017/8/29.
 */
public class JwtHelper {
    private static Logger logger = LoggerFactory.getLogger(JwtHelper.class);
    /**
     * 校验Token
     * @param jwt
     * @param httpRequest
     * @return
     */
    public static int checkToken(String jwt, HttpServletRequest httpRequest){
        if (!StringUtils.isBlank(jwt)){
            if (jwt.split("\\.").length==3) {
                logger.info("jwt:" + jwt);
                String[] split = jwt.split("\\.");
                String content = split[1];
                String s = Base64Codec.BASE64URL.decodeToString(content);
                logger.info("s:" + s);
                String sign = split[2];
                logger.info("sign:" + sign);
                JSONObject jsonObject1 = JSONObject.fromObject(s);
                long nowMillis = System.currentTimeMillis();
                Date now = new Date(nowMillis);
                long expiresSecond = (long) jsonObject1.get("expiresSecond");
                //判断是否过期
                if(now.getTime()>expiresSecond)
                     return 2;
                TokenObject o = (TokenObject) JSONObject.toBean(jsonObject1, TokenObject.class);
                 if (o!=null){
                    String project = o.getProject();
                    if (!StaticInfo.PROJECT.equals(project))
                        return 0;
                }
                String jwtByStr = createJWTByObj(o);
                String s2 = jwtByStr.split("\\.")[2];
                logger.info("s2:" + s2);
                if (sign.equals(s2)) {
                    return 1;
                } else
                    return 0;
            }
        }
        return 0;
    }
    /**
     * 获取用户id
     * @param jwt
     * @return
     */
    public static int  getIdByJWT(String jwt){
        if (!StringUtils.isBlank(jwt)) {
            if (jwt.split("\\.").length == 3) {
                logger.info("jwt:" + jwt);
                String[] split = jwt.split("\\.");
                String content = split[1];
                String s = Base64Codec.BASE64URL.decodeToString(content);
                JSONObject jsonObject1 = JSONObject.fromObject(s);
                TokenObject o = (TokenObject) JSONObject.toBean(jsonObject1, TokenObject.class);
                return o.getaId();
            }
        }
        return 0;
    }
    /**
     * 获取客户信息
     * @param request
     * @return
     * @throws CustomException
     */
    public static int getIdByRequest(HttpServletRequest request) throws CustomException {
        int i = 0;
        String auth = request.getHeader("Authorization");
        if ((auth != null) && (auth.length() > 6)) {
            String HeadStr = auth.substring(0, 5).toLowerCase();
            if (HeadStr.compareTo("basic") == 0) {
                auth = auth.substring(6, auth.length());
                i = JwtHelper.getIdByJWT(auth);
            }
        }
        if (i==0)
            throw new CustomException(ResultEnum.PERMISSION_DENIED);
        return i;
    }
    public static String createJWTByObj(TokenObject tokenObject) {
        JSONObject jsonObject = JSONObject.fromObject(tokenObject);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(tokenObject.getBase64Secret());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setPayload(jsonObject.toString())
                .signWith(signatureAlgorithm, signingKey);
        //生成JWT
        return builder.compact();
    }
}  
6、添加token过滤器 
(如果请求的Header中存在Authorization: Basic 头信息,且用户名密码正确,则继续原来的请求,否则返回没有权限的错误信息)
/**
 * 如果请求的Header中存在Authorization: Basic 头信息,且用户名密码正确,则继续原来的请求,否则返回没有权限的错误信息
 */
@WebFilter(filterName = "colationFilter", urlPatterns= "/colation/*")
public class HTTPBasicAuthorizeAttribute implements Filter{
    private Logger logger = LoggerFactory.getLogger(HTTPBasicAuthorizeAttribute.class);
    @Autowired
    private Audience audience;
    @Override
    public void destroy() {
        logger.info("后台token过滤器,溜了溜了溜了溜了");
        //可以日志管理添加
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        logger.info("后台token过滤器检测");
        //1.检测当前是否需要重新登录
        if(audience!=null){
            if (audience.getClientId().equals(StaticInfo.SIGNOUT)){
                toResponse((HttpServletResponse) response,1,(HttpServletRequest) request);
                return;
            }
        }
        //2.检测请求同token信息
        ResultEnum resultStatusCode = checkHTTPBasicAuthorize(request);
        if (resultStatusCode.equals(ResultEnum.SINGTIMEOUT)){//超时
            toResponse((HttpServletResponse) response, 2,(HttpServletRequest) request);
            return;
        }else if (resultStatusCode.equals(ResultEnum.PERMISSION_DENIED)){//权限不够
            toResponse((HttpServletResponse) response, 0,(HttpServletRequest) request);
            return;
        }
        logger.info("后台token过滤器检测通过");
        chain.doFilter(request, response);
    }
    /**
     * 响应
     * @param response
     * @param i 类型
     * @throws IOException
     */
    private void toResponse(HttpServletResponse response, int i,HttpServletRequest request) throws IOException {
        HttpServletResponse httpResponse = response;
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json; charset=utf-8");
        httpResponse.setHeader("Access-Control-Allow-Origin","*");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PATCH,PUT");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,x-requested-with,X-Custom-Header," +
                "Content-Type,Accept,Authorization");
        String method = request.getMethod();
        if ("OPTIONS".equalsIgnoreCase(method)){
            logger.info("OPTIONS请求");
            httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
        }
        ObjectMapper mapper = new ObjectMapper();
        PrintWriter writer = httpResponse.getWriter();
        if (i==1)
            writer.write(mapper.writeValueAsString(ResultUtils.error(ResultEnum.RESTARTLOGIN)));
        else if (i==2)
            writer.write(mapper.writeValueAsString(ResultUtils.error(ResultEnum.SINGTIMEOUT)));
        else
            writer.write(mapper.writeValueAsString(ResultUtils.error(ResultEnum.PERMISSION_DENIED)));
        writer.close();
        if (writer!=null)
            writer = null;
    }
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        logger.info("后台token过滤器启动");
    }
    /**
     * 检测请求同token信息
     * @param request
     * @return
     */
    private ResultEnum checkHTTPBasicAuthorize(ServletRequest request)
    {
        try
        {
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            String auth = httpRequest.getHeader("Authorization");
            if ((auth != null) && (auth.length() > 6))
            {
                String HeadStr = auth.substring(0, 5).toLowerCase();
                if (HeadStr.compareTo("basic") == 0)
                {
                    auth = auth.substring(6, auth.length());
                    int i = JwtHelper.checkToken(auth, httpRequest);
                    if (i==1) {
                        return ResultEnum.OK;
                    }else if (i==2){
                        return ResultEnum.SINGTIMEOUT;
                    }
                }
            }
            return ResultEnum.PERMISSION_DENIED;
        }
        catch(Exception ex)
        {
            return ResultEnum.PERMISSION_DENIED;
        }
    }
}
7、测试token
/**
 * 登录退出-Controller
 * Created by CatalpaFlat on 2017/8/31.
 */
@RestController
@RequestMapping
public class AccoutController {
    @Autowired
    private AccountService accountService;
    /**
     * 登录
     * @param loginPara
     * @param request
     * @return
     * @throws CustomException
     */
    @PostMapping(value = "oauth/token")
    public Result getToken(LoginPara loginPara, HttpServletRequest request) throws CustomException {
        return accountService.getToken(loginPara,request);
    }
    /**
     * 退出
     * @param request
     * @return
     */
    @PostMapping(value = "singOut")
    public Result singOut(HttpServletRequest request){
        return accountService.singOut(request);
    }
}
/**
 * 登录-ServiceImpl
 * Created by CatalpaFlat on 2017/8/29.
 */
@Service
public class AccountServiceImpl implements AccountService {
    private Logger logger = LoggerFactory.getLogger(AccountServiceImpl.class);
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private Audience audience;
    @Autowired
    private TokenObject tokenObject;
    @Override
    public MangerInfo queryAccountByName(String userName) {
        return accountMapper.queryAccountByName(userName);
    }
    /**
     * 获取token
     * @param loginPara
     * @param request
     * @return
     */
    @Override
    public Result getToken(LoginPara loginPara, HttpServletRequest request) throws CustomException {
        //获取登录ip
        String remoteHost = request.getRemoteHost();
        String md5 = MD5Utils.getMD5(remoteHost);
        logger.info("md5:"+md5);
        loginPara.setClientId(md5);
        //第一个登录者
        if (StaticInfo.SIGNOUT.equals(audience.getClientId())){
            //修改配置文件
            BeanWrapper bean = new BeanWrapperImpl(audience);
            bean.setPropertyValue("clientId", md5);
            audience.setClientId(md5);
        }
        audience.setClientId(md5);
        //校验是否已经登录着
//        if(audience.getClientId()!=null&&(loginPara.getClientId().compareTo(audience.getClientId()) != 0))
//            throw new CustomException(ResultEnum.ISSINGIMG);
        MangerInfo user = queryAccountByName(loginPara.getUserName());
        if (user == null)
            throw new CustomException(ResultEnum.INVALID_PASSWORD);
        else
        {
            String md5Password = MD5Utils.getMD5(loginPara.getPassword()+user.getSalt());
            if (md5Password.compareTo(user.getaPassword()) != 0)
                throw new CustomException(ResultEnum.INVALID_PASSWORD);
        }
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        //拼装accessToken
        tokenObject.setaId(user.getaId());
        tokenObject.setBase64Secret(audience.getBase64Secret());
        tokenObject.setClientId(audience.getClientId());
        tokenObject.setExpiresSecond(audience.getExpiresSecond()+now.getTime());
        tokenObject.setRole(user.getRole());
        tokenObject.setUserName(loginPara.getUserName());
        tokenObject.setName(audience.getName());
        String token = JwtHelper.createJWTByObj(tokenObject);
        //返回accessToken
        AccessToken accessTokenEntity = new AccessToken();
        accessTokenEntity.setAccess_token(token);
        accessTokenEntity.setExpires_in(audience.getExpiresSecond());
        accessTokenEntity.setToken_type("basic");
        return ResultUtils.success(accessTokenEntity);
    }
    @Override
    public Result singOut(HttpServletRequest request) {
        BeanWrapper bean = new BeanWrapperImpl(audience);
        bean.setPropertyValue("clientId",  StaticInfo.SIGNOUT);
        return ResultUtils.success();
    }
}
SpringBoot 基于jjwt快速实现token授权的更多相关文章
- SpringBoot 通过jjwt快速实现token授权
		
A 10分钟了解JSON Web令牌(JWT)https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=p ...
 - 在线Online表单来了!JeecgBoot 2.1 版本发布——基于SpringBoot+AntDesign的快速开发平台
		
项目介绍 Jeecg-Boot 是一款基于SpringBoot+代码生成器的快速开发平台! 采用前后端分离架构:SpringBoot,Ant-Design-Vue,Mybatis,Shiro,JWT. ...
 - 基于SpringBoot+AntDesign的快速开发平台,JeecgBoot 2.0.2 版本发布
		
Jeecg-Boot 是一款基于SpringBoot+代码生成器的快速开发平台! 采用前后端分离架构:SpringBoot,Ant-Design-Vue,Mybatis,Shiro,JWT. 强大的代 ...
 - springboot+jwt做api的token认证
		
本篇和大家分享jwt(json web token)的使用,她主要用来生成接口访问的token和验证,其单独结合springboot来开发api接口token验证很是方便,由于jwt的token中存储 ...
 - SpringBoot系列: RestTemplate 快速入门
		
====================================相关的文章====================================SpringBoot系列: 与Spring R ...
 - Windows Azure Active Directory (1) 前言 - 基于声明的验证和授权
		
<Windows Azure Platform 系列文章目录> 在我们介绍整套系统架构之前,我们需要首先定义一些基本的概念. 用户及其属性: 用户值得是要使用某项服务的个体.用户一般都有一 ...
 - ABP从入门到精通(5):使用基于JWT标准的Token访问WebApi
		
项目:asp.net zero 4.2.0 .net core(1.1) 版本 我们做项目的时候可能会遇到需要提供api给app调用,ABP动态生成的WebApi提供了方便的基于JWT标准的Token ...
 - spring-security实现的token授权
		
在我的用户密码授权文章里介绍了spring-security的工作过程,不了解的同学,可以先看看用户密码授权这篇文章,在 用户密码授权模式里,主要是通过一个登陆页进行授权,然后把授权对象写到sessi ...
 - 基于vue-cli快速构建
		
基于vue-cli快速构建 https://www.jianshu.com/p/2769efeaa10a Vue是近两年来比较火的一个前端框架(渐进式框架吧),与reactjs和angularjs ...
 
随机推荐
- [转] NTFS Permission issue with TAKEOWN & ICACLS
			
(转自:NTFS Permission issue with TAKEOWN & ICACLS - SAUGATA 原文日期:2013.11.19) Most of us using TA ...
 - 中国版 Office 365 (X-Tenant / Tango) 功能验证报告 - 2 基本步骤
			
说明: 1. 前期准备 - 在Azure上模拟出生产环境: 包括父域域控.子域域控.父域的Exchange Server.子域的Exchange Server.对Exchange Server, 需要 ...
 - codevs 1082 线段树练习 3 --分块练习
			
时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[ ...
 - C/C++ 标准输入、输出
			
一.分类 1.标准输入输出 键盘输入,显示器输出.2.文件输入输出 以外存为对象,即硬盘.光盘等.3.串输入输出 对内存中指定空间进行输入输出. 二.c语言中的输入输出 #include <st ...
 - 迅为嵌入式开发板iTOP-6818开发板八核Cortex-A53架构,满足各种产品需求
			
性价比更高 内存:1G(可选2G);存储:16G;4418:四核 Cortex-A9;6818:八核Cortex-A53. 功能更强 板载4G(全网通),GPS,WIFI,千兆以太网,重力加速度计等, ...
 - Java HTTP 组件库选型看这篇就够了
			
最近项目需要使用 Java 重度调用 HTTP API 接口,于是想着封装一个团队公用的 HTTP client lib. 这个库需要支持以下特性: 连接池管理,包括连接创建和超时.空闲连接数控制.每 ...
 - CREATE VIEW - 定义一个视图
			
SYNOPSIS CREATE [ OR REPLACE ] VIEW name [ ( column_name [, ...] ) ] AS query DESCRIPTION 描述 CREATE ...
 - react link引入外部css样式的坑
			
刚开始的代码是这样的,使用react router4.x写的demo路由跳转后,页面的没有渲染,是因为没有引入外部css文件(或者说引入外部文件路径错误) <!DOCTYPE html> ...
 - 小写bool和大写BOOL的区别
			
转:https://blog.csdn.net/ji0525084/article/details/8594469 bool是标准C++中的布尔量,占一个字节大小内存,只有false或者true.具有 ...
 - Ubuntu16.04 python3.4.3升级到python3.7.1
			
python有两个版本,一个2版本,使用的是python:另一个是3版本,使用的是python3. 简易安装python后得到的3版本的版本号是python3.4.3. 可以使用下面的命令查看py版本 ...