JWT(json web token)。
1、jwt(フルネームのjson Webトークン)。これは主に、暗号化された文字列の文字列であるトークンを生成するために使用されます。
プロセスはこのようなものです
- ユーザーがユーザー名とパスワードを使用してサーバーを要求する
- サーバーはユーザー情報を検証し、データベースに保存するトークンを生成します
- サーバーは検証に合格し、トークンをユーザーに送信します
- クライアントはトークンを保存します。通常、ローカルストレージが存在します。そして、このトークン値を各リクエストに追加します。これは、ajaxリクエストヘッダーまたはリクエスト本文にパラメーターとして追加できます。
- サーバーはトークンを検証します。トークンの検証はデータベースに保存されているトークンと比較されます。検証に合格すると、ビジネスロジックが処理され、データが返されます。
利点はこれです
- クロスドメインアクセスのサポート: 送信されたユーザー認証情報がHTTPヘッダーを介して送信される場合、Cookieはトークンメカニズムには存在しないクロスドメインアクセスを許可しません
- モバイルアプリケーションに適しています。クライアントがiOSまたはAndroidの場合、Cookieはサポートされておらず、トークン認証メカニズムははるかに単純です。
- 始めるのは簡単:単純な泥棒。以下で詳しく説明します。
- あなたが推測
2.実装手順(他のブログの紹介を読んだ後、簡単な手順を非常に複雑にしたので、自分で再試行しました)
- pomファイルに依存関係を追加する
<!-- 添加依赖JwtPermission --> <dependency> <groupId>com.github.whvcse.JwtPermission</groupId> <artifactId>jwtp-spring-boot-starter</artifactId> <version>2.0.2</version> </dependency>
- 対応するエンティティ、データベースを追加し、対応するテーブルを作成します。各テーブルの関連付け関係は、テーブル名の文字通りの意味から理解する必要があります。理解できない場合は、次のテーブル作成ステートメントでフィールド注釈の導入を確認できます(最初の5つのsys関連テーブルは対応するエンティティを作成し、トークン関連テーブルはテーブルを作成するだけでよく、エンティティを作成する必要はありません)
1,系统用户表:sys_user
2,系统角色表:sys_role
3,系统权限表:sys_authorities
4,用户角色关联表:sys_user_role
5,角色权限关联表:sys_role_authorities
6,根据jar包中的代码建oauth_token表和oauth_token_key表。
https://download.csdn.net/download/nienianzhi1744/11878539(詳細については、このリンクにあるテーブル作成SQLとテーブル関係の説明を参照してください)
3.ログイン時にユーザー名とパスワードを確認し、渡した後にトークンを作成し、データベースに保存してクライアントに返します。
// 几个公司私有的接口(userJpaService,userRoleService,authoritiesService)没有导入,这几个接口主要写的是根据id查询实体的方法
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.wf.jwtp.provider.Token;
import org.wf.jwtp.provider.TokenStore;
@Api(value = "其他配置——用户登录相关接口", tags = "main")//swagger注解,可以不加
@Controller
public class MainController extends BaseController {
@Autowired
private UserJpaService userJpaService;
@Autowired
private UserRoleJpaService userRoleService;
@Autowired
private AuthoritiesJpaService authoritiesService;
@Autowired
private TokenStore tokenStore;
@ResponseBody
@ApiOperation(value = "用户登录")//ApiOperation和ApiImplicitParams是swgger注解,便于接口API交互,可以不加
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "账号", required = true, dataType = "String", paramType = "form"),
@ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String", paramType = "form")
})
@PostMapping("${api.version}/login")
@Log(describe = "用户登录",operationType= OperationType.LOGON)//此处为自定义注解,用于记录用户操作,可以不加
public Map login(String username, String password) {
Map returnMap=new HashMap<>();
/*根据用户名获取实体*/
User user = userJpaService.getByUsername(username);
/*若数据库中无该用户的数据*/
if(user==null){
returnMap.put("fail","登录失败");
}
/*若密码对不上,数据库中的密码应该是加密的,此处仅为演示不做加密处理*/
else if(!password.equals(user.getPassword())){
returnMap.put("fail","密码输入有误");
}else{
/*根据用户id获取角色的id集合*/
String[] roles = arrayToString(userRoleService.getRoleIds(user.getUserId()));
/*根据用户id获取权限id集合*/
String[] permissions = listToArray(authoritiesService.listByUserId(user.getUserId()));
/*调用TokenStore的createNewToken创建token*/
Token token = tokenStore.createNewToken(String.valueOf(user.getUserId()), permissions, roles);
returnMap.put("success","登录成功");
returnMap.put("access_token",token.getAccessToken());
}
return returnMap;
}
private String[] listToArray(List<String> list) {
String[] strs = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
strs[i] = list.get(i);
}
return strs;
}
private String[] arrayToString(Object[] objs) {
String[] strs = new String[objs.length];
for (int i = 0; i < objs.length; i++) {
strs[i] = String.valueOf(objs[i]);
}
return strs;
}
}
クライアントが返されたマップでトークンを受け取った後、それは渡されます
localStorage.setItem("key","value")将map中的token值存到localstorage。
4.最後のステップ、このステップは簡単です。
ログイン後、後続のAjaxビジネスリクエストで、トークン値をlocalstorageに取り込み、バックグラウンドでデータベースの値を使用して確認します。この方法はもっとです。
次の戦略(非推奨)について説明し、トークンをパラメーターとしてバックグラウンドに直接配置し、バックグラウンドで受信して検証します。
最良のポリシーについて話しましょう(推奨):
フロントエンド:ajaxリクエストを再パッケージ化します。トークンの値をリクエストヘッダーに入れます。このように、Ajaxを使用するたびにトークンを追加する必要はありません。このパッケージ化されたAjaxを直接呼び出して、直接使用することができます。
var token=localStorage.getItem("key")
$.ajax({
type: "post",
url:"xxx",
contentType: "application/json;charset=utf-8",
data :JSON.stringify({"tbId": 1}),
dataType: "json",
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Authorization", "Bearer "+token);
},
success: function (data) {
alert(data);
},error:function(error){
console.log(error);
}
)
バックエンド:Swaggerアノテーションを構成します。Swaggerの構成では、パラメーターの要求ヘッダーが必要です。リクエストされたインターフェイスにスワッパーアノテーションを追加して、リクエストヘッダーのトークンを確認します。
1.pomの依存関係を追加します
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
2.Swagger構成
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.Parameter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.xxx.xxx.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(headerInfo());//************把消息头添加;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API文档")
.description("后台管理系统")
.termsOfServiceUrl("")
.version("1.0")
.build();
}
private List<Parameter> headerInfo(){
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<Parameter>();
ticketPar.name("Authorization").description("access_token")//name表示名称,description表示描述
.modelRef(new ModelRef("string")).parameterType("header")
.required(true).defaultValue("Bearer ").build();//required表示是否必填,defaultvalue表示默认值
pars.add(ticketPar.build());//添加完此处一定要把下边的带***的也加上否则不生效
return pars;
}
}
3.図に示すように、インターフェイスにSwagger注釈を追加します
このように、Swaggerアノテーションを使用するインターフェースは、要求されたときに、要求の要求ヘッダー内のトークンを自動的にチェックします。