Введение
Каждый веб-сайт размером с страницу H5 должен иметь модуль аутентификации и авторизации при входе.Каковы распространенные методы аутентификации и авторизации? Как этого добиться? Далее мы объясним SSO, OAuth и другие связанные знания в будущем, а также применим положение на практике.
2. Аутентификация и авторизация
Эти два термина часто используются в сочетании друг с другом с точки зрения безопасности, особенно при получении доступа к системе. Обе темы очень важны и часто связаны с сетью как с ключевой частью ее сервисной инфраструктуры. Тем не менее, два термина очень разные по совершенно разным концепциям. Хотя они часто используются в одном контексте с использованием одних и тех же инструментов, они сильно отличаются друг от друга.
Аутентификация означает подтверждение вашей личности, а авторизация означает предоставление доступа к системе. Проще говоря, аутентификация — это процесс проверки вашей личности, тогда как авторизация — это процесс проверки наличия у вас доступа.
Аутентификация доказывает, что вы — это вы, а авторизация доказывает, что у вас есть эти полномочия. Аутентификация — это первый шаг в авторизации и, следовательно, всегда первый. Авторизация выполняется после успешной аутентификации.
Пример: Вам необходимо войти на форум, ввести имя пользователя Zhang San и пароль 1234. Пароль правильный, что доказывает, что Zhang San действительно является Zhang San. Это аутентификация, затем проверьте, что пользователь Zhang San является модератором, поэтому он имеет право добавлять и удалять чужие сообщения. , что является авторизацией.
3. Единый вход (SSO)
Единый вход или сокращенно SSO — одно из самых популярных решений для корпоративной бизнес-интеграции. Определение SSO заключается в том, что в системах с несколькими приложениями пользователям необходимо войти в систему только один раз, чтобы получить доступ ко всем взаимно доверенным системам приложений.
Например, QQ Music и Tencent News — это две разные прикладные системы в Tencent.Если пользователю не нужно снова входить в систему при доступе к QQ Music после входа в Tencent News, это означает, что существует разница между QQ Music и Tencent. Новости Реализован единый вход.
3.1 Файлы cookie родительского домена
Самый простой способ сделать это — установить атрибут домена файла cookie на родительский домен текущего домена, тогда он считается файлом cookie родительского домена. Файл cookie имеет функцию, при которой файл cookie в родительском домене используется субдоменом, другими словами, субдомен автоматически наследует файлы cookie в родительском домене.
- Система 1: a.zxy.com
- Система 2: b.zxy.com
- Система входа: login.zxy.com
3.2 CAS
Есть еще один способ, то есть CAS (Central Authentication Service) (Центральная служба аутентификации). Вы можете обратиться к OAuth2.0, система приложения проверяет, есть ли у текущего запроса Тикет, если нет, то это означает, что пользователь не авторизовался в текущей системе, и страница будет перенаправлена в центр аутентификации. Поскольку эта операция автоматически доставляет файл cookie центра аутентификации, центр аутентификации может узнать, вошел ли пользователь в систему на основе файла cookie. Если центр аутентификации обнаружит, что пользователь не вошел в систему, он вернется на страницу входа и будет ждать, пока пользователь войдет в систему. Если он обнаружит, что пользователь уже вошел в систему, он не позволит пользователю снова войти в систему, но вернется к целевому URL-адресу и сгенерирует URL-адрес перед переходом.Билет, склеенный за целевым URL-адресом и отправленный обратно в целевую систему приложений.
4. ОАут
4.1 Четыре способа
OAuth 2.0 определяет четыре метода авторизации.
- Код авторизации
- Упрощенный режим (неявный)
- Режим пароля (учетные данные пароля владельца ресурса)
- Режим клиента (учетные данные клиента)
4.1.1 Режим кода авторизации
Режим кода авторизации (код авторизации) — это режим авторизации с наиболее полными функциями и самым строгим процессом. Он характеризуется взаимодействием с сервером аутентификации «поставщика услуг» через фоновый сервер клиента.
Часть описания на приведенном выше рисунке дополнена
- response_type=code&client_id={идентификатор клиента}&redirect_uri={URI перенаправления}&scope={область полномочий}&state={состояние}
- URL-адрес перенаправления?code={code}&state={state}
- URL-адрес перенаправления?code={code}&state={state}
- grant_type=authorization_code&client_id={client_id}&code={code}&state={state}&redirect_uri={redirect_uri}
4.1.2 Упрощенный режим
Упрощенный режим (тип неявного гранта) не проходит через сервер стороннего приложения, а напрямую запрашивает токен с сервера аутентификации в браузере, пропуская шаг «код авторизации», отсюда и название. Все шаги выполняются в браузере, токен виден посетителю, а клиент не требует аутентификации.
Часть описания на приведенном выше рисунке дополнена
- авторизовать?response_type=token&client_id={ID клиента}&redirect_uri={URI перенаправления}&scope={область полномочий}&state={state}
- expires_in состояние области access_token refresh_token и включает токен доступа в хэш-часть URI.
4.1.3 Режим пароля
В режиме пароля (предоставление учетных данных владельца ресурса) пользователь предоставляет клиенту свое имя пользователя и пароль. Клиент использует эту информацию для запроса авторизации у «поставщика услуг».
- grant_type=password&username={имя пользователя}&password={пароль}&scope={область полномочий}
4.1.4 Режим клиента
Режим клиента (предоставление учетных данных клиента) означает, что клиент аутентифицируется у «поставщика услуг» от своего имени, а не от имени пользователя. Строго говоря, клиентский режим не является частью проблемы, которую призван решить фреймворк OAuth. В этом режиме пользователь регистрируется напрямую у клиента, а клиент запрашивает у «поставщика услуг» предоставление услуг от своего имени, по сути проблемы с авторизацией не возникает.
4.2 Обновить токен
Если срок действия «токена доступа» клиента истек при доступе пользователя, вам необходимо использовать «токен обновления», чтобы подать заявку на новый токен доступа.
4.3 Пример входа в апплет WeChat
Апплет может легко получить идентификатор пользователя, предоставленный WeChat, с помощью возможности входа в систему, предоставленной официальным лицом WeChat, и быстро установить пользовательскую систему в апплете.
Используется режим кода авторизации в OAuth2.0. Вызовите wx.login(), чтобы получить временный код для входа в систему и отправить его обратно на сервер разработчика. Вызов интерфейса auth.code2Session в обмен на уникальный идентификатор пользователя OpenID, уникальный идентификатор пользователя UnionID под учетной записью WeChat Open Platform (если текущая мини-программа привязана к учетной записи WeChat Open Platform) и сеансовый ключ session_key. После этого сервер разработчика может сгенерировать пользовательское состояние входа в систему в соответствии с идентификатором пользователя, который используется для идентификации идентификатора пользователя во время взаимодействия между интерфейсом и сервером в последующей бизнес-логике.
5. ЮВТ
JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный автономный способ безопасной передачи информации между сторонами в виде объектов JSON. Эту информацию можно проверить и доверять ей, поскольку она имеет цифровую подпись.
Наиболее распространенный сценарий JWT: после входа пользователя в систему каждый последующий запрос будет содержать JWT, позволяя пользователю получить доступ к маршрутам, службам и ресурсам, разрешенным токеном. Единый вход — это функция JWT, которая сейчас широко используется, потому что она не требует больших затрат и может легко использоваться в разных доменах.
JWT состоит из трех частей, которые соединены точками «.». Три части: заголовок, полезная нагрузка, подпись. Итак, типичный JWT выглядит так: "xxx.yyy.zzz"
Первая часть заголовка JWT обычно состоит из двух частей: типа («JWT») и имени алгоритма (например: HMAC SHA256 или RSA и т. д.).
{
"alg": "HS256",
"typ": "JWT"
}
Во второй части полезной нагрузки JWT, в которой хранятся наши данные, обратите особое внимание на то, чтобы не хранить в ней конфиденциальную информацию. Он содержит утверждения, которые являются утверждениями о сущностях (обычно о пользователях) и других данных. Существует три типа объявлений: зарегистрированные, публичные и частные.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Третья часть JWT, подпись, чтобы получить часть подписи, у вас должен быть закодированный заголовок, закодированная полезная нагрузка и секретный ключ.Алгоритм подписи указан в заголовке, и тогда вы можете подписать их.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Java-реализация
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
public class Test {
private static final Logger logger = LoggerFactory.getLogger(Test.class);
private static String secret = "zhongxy@123456";
private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) throws Exception {
UserInfo userInfo = new UserInfo(); // 自定义的登录对象
userInfo.setId(6);
userInfo.setName("测试");
logger.info("UserInfo:" + objectMapper.writeValueAsString(userInfo));
String token = generateToken(userInfo, 60 * 1000);
logger.info("token:" + token);
Object result = check(token);
logger.info("check:" + objectMapper.writeValueAsString(result));
}
// 生成token
public static String generateToken(UserInfo userInfo, long ttlSecs) {
//The JWT signature algorithm we will be using to sign the token
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//We will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secret);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
//Let's set the JWT Claims
JwtBuilder builder = null;
try {
builder = Jwts.builder()
.setIssuedAt(now)
.setIssuer(objectMapper.writeValueAsString(userInfo))
.signWith(signatureAlgorithm, signingKey);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
//if it has been specified, let's add the expiration
if (ttlSecs >= 0) {
long expMillis = nowMillis + ttlSecs * 1000;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
//Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}
// 从token中反向解析出UserInfo
public static UserInfo check(String token) {
try {
//This line will throw an exception if it is not a signed JWS (as expected)
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(secret))
.parseClaimsJws(token).getBody();
String userInfoStr = claims.getIssuer();
return objectMapper.readValue(userInfoStr, UserInfo.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}