鍵マント+springセキュリティトークンリリース年代

47531 ワード

私はkeycook APIの公式ドキュメントの方法に従ってaccesstokenを取得することを選択しました.
しかし、ほとんどのブログ記事はspringsecurityにバインドされています.
その時私は知識が足りなかったのに、どうしてそんなことをしたのですか.と思った.
すべて原因がある.
なぜなら、必要な情報をjsonパケット化するためにaccesstokenを私のように直接復号する方法です.
あまりよくないのは...まず,MSAベースの各サービスにはそれぞれのサーバがある.
サーバが異なる場合、モデルもセッションも無駄です.
だからspring-httpsessionではredisを使うことが多い.
ただし、ログアウト機能を実装している場合はredisを使用する必要があります.
ログアウト機能以外はログイン機能のみで、redisタグなしでの移動が許可されている場合は、
次に~springsecurityとkeycoatkがあり、トークン情報をprincipalオブジェクトに格納する.
KEYマントAccesstokenをjwtTokenに変換します.
すなわち、tokenのuserinfoはgetUserAttributes()として受信される.
やってみようぜ!

まず鍵マントをgatewayに接続します


SecurityConfig.java

package com.dream.gatewayservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
public class SecurityConfig {
	
	@Bean
	public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
		http.authorizeExchange().pathMatchers("/menu/**").permitAll()
			.and().authorizeExchange().anyExchange().authenticated()
			.and().oauth2Login() // to redirect to oauth2 login page.
			.and().csrf().disable();
		return http.build();
	}
}
まず安心感を設定します.

application.yml

  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: http://너님의 키클락사용할 pc url:8080/auth/realms/MSA
        registration:
          keycloak:
#            provider: keycloak
            client-id: spring-gateway-client
            client-secret: 클라이언트 비번
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/keycloak'      
            
keycloak:
  realm: MSA
#  public-client: false
  resource: spring-gateway-client
  auth-server-url: http://너님의 키클락사용할 pc url:8080/auth
このような
鍵のマントの情報を知るから~!

build.gradle

plugins {
	id 'org.springframework.boot' version '2.6.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.dream'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "2021.0.1")
	set('keyCloakVersion', "16.1.1") //추가
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' //추가
	implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
	//implementation 'org.keycloak:keycloak-spring-boot-starter'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
		mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keyCloakVersion}" //추가
	}
}

tasks.named('test') {
	useJUnitPlatform()
}
//追加と書かれたすべての部分を追加します.それは鍵マントが縛られていることです.

鍵マントをMSに安全に接続してトークンを取得する


ManageConfig.java


package com.dream.manage.config;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class ManageConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().anyRequest().authenticated()
				.and().oauth2ResourceServer()
                .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))
				.and().anonymous().disable();
	}

	private Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter() {
		JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
		jwtConverter.setJwtGrantedAuthoritiesConverter(new RealmRoleConverter());
		return jwtConverter;
	}

	public class RealmRoleConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
		@Override
		public Collection<GrantedAuthority> convert(Jwt jwt) {
			final Map<String, List<String>> realmAccess = (Map<String, List<String>>) jwt.getClaims()
					.get("realm_access");
			return realmAccess.get("roles").stream().map(roleName -> "ROLE_" + roleName) 
            // prefix required by Spring
																							
           // Security for roles.
					.map(SimpleGrantedAuthority::new).collect(Collectors.toList());
		}
	}
}
まずconfigは各サービスに対して行うべきである.

application.yml

  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://keycloak 돌릴 pc url:8080/auth/realms/MSA/protocol/openid-connect/certs
#      client:
#        provider:
#          keycloak:
#            issuer-uri: http://keycloak 돌릴 pc url:8080/auth/realms/MSA
#        registration:
#          keycloak:
##            provider: keycloak
#            client-id: spring-gateway-client
#            client-secret: keycloak client 비번
#            authorization-grant-type: authorization_code
#            redirect-uri: '{baseUrl}/login/oauth2/code/keycloak' 
keycloak:
  realm: MSA
  bearer-only: true
  ssl-required: external
  resource: spring-gateway-client
  auth-server-url: http://keycloak 돌릴 pc url:8080/auth
  credentials:
    secret: keycloak client 비번
これを入れてください.

build.gradle

plugins {
	id 'org.springframework.boot' version '2.6.4'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.dream'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "2021.0.1")
	set('keycloakversion', "16.1.1") //추가
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' //추가
	implementation 'org.springframework.boot:spring-boot-starter-security' //추가
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.keycloak:keycloak-spring-boot-starter' //추가
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
	implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'mysql:mysql-connector-java'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
		mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keycloakversion}" //추가
	}
}

tasks.named('test') {
	useJUnitPlatform()
}
//追加するすべての部分を追加してください
次にcontrollerからtokenを抽出し、tokenに必要な情報をビューに渡します.
やってみます~

manageController.Javaの変更が必要です

package com.dream.manage.controller;

import java.security.Principal;

import javax.annotation.security.RolesAllowed;

import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.dream.manage.dto.ManageDto;
import com.dream.manage.service.ManageService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequiredArgsConstructor
@Slf4j
public class ManageController {
	private ManageService service;

	@RolesAllowed({ "ADMIN" }) //realm 의 role에 따라 mapping
	@GetMapping("/register")
	public String register(Principal principal, Model model) {
		JwtAuthenticationToken token = (JwtAuthenticationToken) principal; //jwt로 형변환
		log.info("toString : "+token.getTokenAttributes().toString());
		model.addAttribute("list", token.getTokenAttributes());
		return "register";
	}

	@RolesAllowed({ "ADMIN" })
	@PostMapping("/register")
	public String register(@ModelAttribute("dto") ManageDto dto) {
		log.info("컨트롤러 시작" + dto.getDescription());
		service.register(dto);
		log.info("컨트롤러 끝");
		return "/regist_success";
	}

	@PostMapping("/modify")
	public String modify() {
		return "asd";
	}

	@GetMapping("/delete")
	public String delete() {
		return "asd";
	}
}
register.htmlでは、
<div th:text="${list.preferred_username}"> 
出して使えばいいです.
これで他のMSも可能です.

結果



まずlocalhost:8000/manage/registerにユーザーとしてアクセスします.
ポート番号8000はapiゲートウェイポート番号です.

@RolesAllowed({"ADMIN"})によって拒否されました
今回はadminアクセスを使ってみました


このようにusernameが現れているのが見えます.