1. 程式人生 > >生成token和驗證token機制

生成token和驗證token機制

1.生成token是一個spring控制器
 基於專案和專案之間的呼叫祕鑰生成之後放redis,兩小時後失效

package com.csair.openapi.controller.basic;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.csair.openapi.basic.annotation.WEBApi;
import com.csair.openapi.qo.sub.TokenCredential;
import com.csair.openapi.vo.sub.TokenSuccess;

@RestController
@RequestMapping("/credential")
public class TokenCredentialController {

	
	@Autowired
	private RedisTemplate<String, String> redisTemplate;


	private Map<String, String> key = new HashMap<String, String>();

	
	@PostConstruct
	public void init() {
		key.put("lps", "lrKvmMg3h9c8UQsvzDn0S4X");
		
	}

	 @RequestMapping(value = "/getToken")
	 @ResponseBody
	 @WEBApi
	 public Object export(HttpServletRequest request,HttpServletResponse response,@RequestBody TokenCredential limitsAuthority) throws Exception {
		 TokenSuccess tokenSuccess   =  new TokenSuccess();
		 if (limitsAuthority!=null&&limitsAuthority.getAppid()!=null&&limitsAuthority.getSecret()!=null) {//校驗使用者是否有許可權
			 String appid= limitsAuthority.getAppid();
			 String secretPass =(String) key.get(appid);
			 String secret = limitsAuthority.getSecret();
			 if (secret.equals(secretPass)) {
				 String Timestamp= System.currentTimeMillis()+"";
				 String token = md5Password(appid+secretPass+System.currentTimeMillis()+Timestamp);
				 redisTemplate.opsForValue().set(token, Timestamp,7200, TimeUnit.SECONDS);//token和驗證碼對應的放到redis裡面 ,2小時秒過期
				 tokenSuccess.setAccess_token(token);
				 tokenSuccess.setExpires_in("7200");
				 return tokenSuccess;
			 }else{
				 throw new RuntimeException("invalid secret");			
			}
		 }
		 throw new RuntimeException("invalid appid");

	 }

 
	
	/**
     * 生成32位md5碼
     * @param password
     * @return
     */
	public static String md5Password(String password) {

		try {
			// 得到一個資訊摘要器
			MessageDigest digest = MessageDigest.getInstance("md5");
			byte[] result = digest.digest(password.getBytes());
			StringBuffer buffer = new StringBuffer();
			// 把每一個byte 做一個與運算 0xff;
			for (byte b : result) {
				// 與運算
				int number = b & 0xff;// 加鹽
				String str = Integer.toHexString(number);
				if (str.length() == 1) {
					buffer.append("0");
				}
				buffer.append(str);
			}
			// 標準的md5加密後的結果
			return buffer.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return "";
		}
	}
	
}

2.用java自定義註解引入aop來鑑權

package com.csair.openapi.basic.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthToken {
	

}
package com.csair.openapi.basic.aspect;


import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.csair.cocc.basic.constant.EnvironmentEnum;
import com.csair.openapi.basic.annotation.AuthToken;

@Component
@Aspect
public class AuthTokenDecorator implements Ordered {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private RedisTemplate<String, String> redisTemplate;
	@Value("${environment}")
	private String environment;

	@Around("within(com.csair.**.controller.**.*) && @annotation(authToken)")
	public Object decorate(ProceedingJoinPoint pjp, AuthToken authToken) throws Throwable {
		 
	  if (EnvironmentEnum.DEV.getValue().equals(environment)) {//如果是開發環境
			return pjp.proceed();//這個是可以繼續傳輸物件到Controller的邏輯
	  }
		
	  Object[] obj = pjp.getArgs();
	  HttpServletRequest request = (HttpServletRequest) obj[0];
	  String accessToken = request.getParameter("accessToken");
	  logger.info("accessToken值為:"+accessToken);
	  
	  if (StringUtils.isEmpty(accessToken)) {
			 throw new RuntimeException("token is null");		
		}else {
			String timestamp = redisTemplate.opsForValue().get(accessToken); 
			if (StringUtils.isEmpty(timestamp)) {
			 throw new RuntimeException("Invalid token");		
			}
		}
		return pjp.proceed();
	}

	public int getOrder() {
		return 9;
	}
	
}

引用redis的配置!

​
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

	<context:property-placeholder location="classpath:redis.properties" />

	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="5000" />
		<property name="maxIdle" value="2000" />
		<property name="maxWaitMillis" value="4000" />
		<property name="testOnBorrow" value="true" />
		<property name="testOnReturn" value="true" />
		<property name="testWhileIdle" value="true" />
	</bean>

	<bean id="redisSentinelConfiguration"
		class="org.springframework.data.redis.connection.RedisSentinelConfiguration">

		<property name="master">
			<bean class="org.springframework.data.redis.connection.RedisNode">
				<property name="name" value="${redis.master.name}"></property>
			</bean>
		</property>

		<property name="sentinels">
			<set>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel1.host}"></constructor-arg>
					<constructor-arg name="port" value="${redis.sentinel1.port}"></constructor-arg>
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel2.host}"></constructor-arg>
					<constructor-arg name="port" value="${redis.sentinel2.port}"></constructor-arg>
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel3.host}"></constructor-arg>
					<constructor-arg name="port" value="${redis.sentinel3.port}"></constructor-arg>
				</bean>
			</set>
		</property>

	</bean>

	<bean id="jedisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="password" value="${redis.password}" />
		<property name="poolConfig" ref="jedisPoolConfig" />
		<constructor-arg ref="redisSentinelConfiguration" />
	</bean>

	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory" />
		<property name="keySerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="hashKeySerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="hashValueSerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
	</bean>

</beans>

​

最重要的是Controller的入參要加上HttpServletRequest request

    @RequestMapping(value = "/saveCargoPlaneUploadLpsInfo", method = RequestMethod.POST)
    @ResponseBody
    @WEBApi
    @AuthToken
    public Object saveCargoPlaneUploadLpsInfo(HttpServletRequest request,@RequestBody CargoPlaneUploadLpsInfoDto param)