zoukankan      html  css  js  c++  java
  • 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();
        }
    }
    测试结果
    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DuShiWoDeCuo/article/details/78180701
  • 相关阅读:
    Cassandra 分页 读取数据
    cassandra高级操作之索引、排序以及分页
    cassandra 可视化工具
    SpringBoot集成Cassandra参考文章
    022 android studio 首次启动时默认的sdk安装路径
    021 Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout)
    020 本机Gradle目录 Could not find com.android.tools.build:gradle:4.1
    019 Android Studio打开XML文件Design显示Waiting for build to finish
    018 Could not download espresso-core-3.2.0.aar (androidx.test.espresso:espresso-core:3.2.0)
    017 Android Studio is using the following JDK location when running Gradle:
  • 原文地址:https://www.cnblogs.com/stupidMartian/p/9262980.html
Copyright © 2011-2022 走看看