1. 程式人生 > >開放平臺之安全河北快三開獎網平臺出租

開放平臺之安全河北快三開獎網平臺出租

平臺安全 開放 快三 源碼

開放平臺就是河北快三開獎網平臺出租1151880099.com請添加鏈接描述 ?1706 186 3513河北快三開獎網平臺出租
技術分享圖片
將企業中的業務的核心部分經過抽象和提取,形成面向企業或者面向用戶的增值系統,為企業帶來新的業務增漲點。

因為是企業的核心業務能力,所以平臺的安全性就成為重中之重。
image
安全方案

普通的接口使用Token令牌的方案就可以保證,但是對於一些敏感的接口就需要有針對性的處理,比如使用https。
https是在http超文本傳輸協議加入SSL層,它在網絡間通信是加密的,所以需要加密證書。
https協議需要ca證書,一般需要交費。
簽名的設計一般是通過用戶和密碼的校驗,然後針對用戶生成一個唯一的Token令牌,

用戶再次獲取信息時,帶上此令牌,如果令牌正確,則返回數據。對於獲取Token信息後,訪問用戶相關接口,客戶端請求的url需要帶上如下參數:
時間戳:timestamp
Token令牌:token
jwt

JWT(json web token)是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準。
JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源。比如用在用戶登錄上。
image
那麽jwt到底長什麽樣呢?
第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload),第三部分是簽證(signature)。
header
jwt的頭部承載兩部分信息:

聲明類型,這裏是jwt
聲明加密的算法 通常直接使用 HMAC SHA256
完整的頭部就像下面這樣的JSON:
{
"typ": "JWT",
"alg": "HS256"
}
然後將頭部進行base64加密(該加密是可以對稱解密的),構成了第一部分:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
playload
載荷就是存放有效信息的地方。這個名字像是特指飛機上承載的貨品,這些有效信息包含三個部分
標準中註冊的聲明
公共的聲明
私有的聲明
標準中註冊的聲明 (建議但不強制使用) :
iss: jwt簽發者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過期時間,這個過期時間必須要大於簽發時間
nbf: 定義在什麽時間之前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
公共的聲明 :
公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密.
私有的聲明 :
私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味著該部分信息可以歸類為明文信息。
定義一個payload:
{
"name":"Free碼農",
"age":"28",
"org":"今日頭條"
}
然後將其進行base64加密,得到Jwt的第二部分:
eyJvcmciOiLku4rml6XlpLTmnaEiLCJuYW1lIjoiRnJlZeeggeWGnCIsImV4cCI6MTUxNDM1NjEwMywiaWF0IjoxNTE0MzU2MDQzLCJhZ2UiOiIyOCJ9
signature
jwt的第三部分是一個簽證信息,這個簽證信息由三部分組成:
header (base64後的)
payload (base64後的)
secret
這個部分需要base64加密後的header和base64加密後的payload使用.連接組成的字符串,然後通過header中聲明的加密方式進行加鹽secret組合加密,然後就構成了jwt的第三部分:
49UF72vSkj-sA4aHHiYN5eoZ9Nb4w5Vb45PsLF7x_NY
密鑰secret是保存在服務端的,服務端會根據這個密鑰進行生成token和驗證,所以需要保護好。
jwt工作流程

下面是一個JWT的工作流程圖。
用戶導航到登錄頁,輸入用戶名、密碼,進行登錄
服務器驗證登錄鑒權,如果改用戶合法,根據用戶的信息和服務器的規則生成JWT Token
服務器將該token以json形式返回(不一定要json形式,這裏說的是一種常見的做法)
用戶得到token,存在localStorage、cookie或其它數據存儲形式中。
以後用戶請求/protected中的API時,在請求的header中加入 Authorization: Bearer xxxx(token)。此處註意token之前有一個7字符長度的 Bearer
服務器端對此token進行檢驗,如果合法就解析其中內容,根據其擁有的權限和自己的業務邏輯給出對應的響應結果。
用戶取得結果
image

spring boot整合jwt

首先,加入依賴
復制代碼
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.45</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.0</version>
    </dependency>

復制代碼
配置信息代碼如下:
復制代碼

JACKSON

spring:
jackson:
serialization:
INDENT_OUTPUT: true

jwt:
header: Authorization
secret: mySecret
expiration: 604800
route:
authentication:
path: auth
refresh: refresh復制代碼
token處理類為JwtTokenUtil,代碼如下:
復制代碼
@Component
br/>復制代碼
token處理類為JwtTokenUtil,代碼如下:
復制代碼
@Component

private static final long serialVersionUID = -3301605591108950415L;

static final String CLAIM_KEY_USERNAME = "sub";
static final String CLAIM_KEY_AUDIENCE = "aud";
static final String CLAIM_KEY_CREATED = "iat";

static final String AUDIENCE_UNKNOWN = "unknown";
static final String AUDIENCE_WEB = "web";
static final String AUDIENCE_MOBILE = "mobile";
static final String AUDIENCE_TABLET = "tablet";

@Autowired
private TimeProvider timeProvider;

@Value("${jwt.secret}")
private String secret;

@Value("${jwt.expiration}")
private Long expiration;

public String getUsernameFromToken(String token) {
    return getClaimFromToken(token, Claims::getSubject);
}

public Date getIssuedAtDateFromToken(String token) {
    return getClaimFromToken(token, Claims::getIssuedAt);
}

public Date getExpirationDateFromToken(String token) {
    return getClaimFromToken(token, Claims::getExpiration);
}

public String getAudienceFromToken(String token) {
    return getClaimFromToken(token, Claims::getAudience);
}

public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
    final Claims claims = getAllClaimsFromToken(token);
    return claimsResolver.apply(claims);
}

private Claims getAllClaimsFromToken(String token) {
    return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody();
}

private Boolean isTokenExpired(String token) {
    final Date expiration = getExpirationDateFromToken(token);
    return expiration.before(timeProvider.now());
}

private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
    return (lastPasswordReset != null && created.before(lastPasswordReset));
}

private String generateAudience(Device device) {
    String audience = AUDIENCE_UNKNOWN;
    if (device.isNormal()) {
        audience = AUDIENCE_WEB;
    } else if (device.isTablet()) {
        audience = AUDIENCE_TABLET;
    } else if (device.isMobile()) {
        audience = AUDIENCE_MOBILE;
    }
    return audience;
}

private Boolean ignoreTokenExpiration(String token) {
    String audience = getAudienceFromToken(token);
    return (AUDIENCE_TABLET.equals(audience) || AUDIENCE_MOBILE.equals(audience));
}

public String generateToken(UserDetails userDetails, Device device) {
    Map<String, Object> claims = new HashMap<>();
    return doGenerateToken(claims, userDetails.getUsername(), generateAudience(device));
}

private String doGenerateToken(Map<String, Object> claims, String subject, String audience) {
    final Date createdDate = timeProvider.now();
    final Date expirationDate = calculateExpirationDate(createdDate);

    System.out.println("doGenerateToken " + createdDate);

    return Jwts.builder()
            .setClaims(claims)
            .setSubject(subject)
            .setAudience(audience)
            .setIssuedAt(createdDate)
            .setExpiration(expirationDate)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
}

public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
    final Date created = getIssuedAtDateFromToken(token);
    return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
            && (!isTokenExpired(token) || ignoreTokenExpiration(token));
}

public String refreshToken(String token) {
    final Date createdDate = timeProvider.now();
    final Date expirationDate = calculateExpirationDate(createdDate);

    final Claims claims = getAllClaimsFromToken(token);
    claims.setIssuedAt(createdDate);
    claims.setExpiration(expirationDate);

    return Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
}

public Boolean validateToken(String token, UserDetails userDetails) {
    JwtUser user = (JwtUser) userDetails;
    final String username = getUsernameFromToken(token);
    final Date created = getIssuedAtDateFromToken(token);
    //final Date expiration = getExpirationDateFromToken(token);
    return (
          username.equals(user.getUsername())
                && !isTokenExpired(token)
                && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
    );
}

private Date calculateExpirationDate(Date createdDate) {
    return new Date(createdDate.getTime() + expiration * 1000);
}

}
復制代碼
最後,在控制層對token的處理進行調用,就能夠完成用戶的權限認證。
測試

啟動應用,然後輸入http://localhost:8080,我們能夠看到測試頁面
image
當輸入用戶名為admin並且登錄成功時,點擊右側的按鈕能夠調用相應的接口。當登錄不成功時,會返回401錯誤。
當輸入用戶名為user並且登錄成功時,只能訪問普通用戶權限的接口,不能訪問管理用戶權限的接口。

開放平臺之安全河北快三開獎網平臺出租