Tekies Communityバックエンドの作成-6


今.今まで制作していたRDBを送ってきます.
毎回コインをつけて化粧直しをするので
だから申請します.構文をpropertiesに挿入する場合は、次の操作を行います.
db.を自動的に作成します.createが終わったらdrop...updateがあればそれを使いますが、なければ作ってください.
spring.jpa.hibernate.ddl-auto=update

これで、Securityとjwtでログインを実現します.
では今はGradlebuildでは、次の依存設定を行う必要があります.
    implementation ('org.springframework.boot:spring-boot-starter-security')
    implementation ('org.springframework.boot:spring-boot-starter-validation')
    implementation group : 'com.googlecode.json-simple', name: 'json-simple', version: '1.1'
    implementation ('io.jsonwebtoken:jjwt:0.9.1')
AccessTokenによってアクセスされる方式でトークン方式で行われます.
ただし、AccessTokenにRefreshTokenの機能を追加すると、よりクリーンになる可能性があります.筆者は.初めまして...まずはAccessTokenをしましょうしました.
前に作ったものもあります.dbを変更するには...以降、JPAモードを使用する場合は、EntityにRDBを適用する方式で行う.
つまりその前にもdbを全部削除していました.上のddl-auto update...
だからEntityからユーザーが変わりました.
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int tc_num;
    private String tc_id;
    private String tc_password;
    private String tc_email;
    @ElementCollection(fetch = FetchType.EAGER)
    private List<String> roles = new ArrayList<>();


    @Builder
    public User(String tc_id, String tc_password, String tc_email) {
        this.tc_id = tc_id;
        this.tc_password = tc_password;
        this.tc_email = tc_email;
        this.roles = Collections.singletonList("ROLE_USER");
    }

    public void update(String tc_password, String tc_email) {
        this.tc_password = tc_password;
        this.tc_email = tc_email;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.roles.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return tc_password;
    }

    @Override
    public String getUsername() {
        return tc_id;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}
Spring Securityのuserdetailを継承するとArreget部分が...これは発表せざるを得ない部分です.キャラクターもstreamは、ロールをstringとして作成し、次の手順で変換する必要があります.
これを変えたら、サービスも変えなければなりません.
public class UserService implements UserDetailsService {
    private final UserRepository userRepository;
    @Override
    public User loadUserByUsername(String username) throws UsernameNotFoundException {

        return userRepository.findtc_passwordBytc_id(username);
    }
}
userServiceの高セキュリティの詳細サービスを継承し、次の変更を行います.
では、サービスとエンティティの準備が完了しました.
そしてsecurityを設定したら….大きく振って移動すると...起動できません...
だからSecurityConfigJavaを次のように記述します.
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors().and()
                .csrf().disable()
                .formLogin().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
こうなると、まず大振りに対して一時的な方法をとるが、追加で変更しなければならない.この部分はjwt部分が終わってからまた来ましょう.
@Component
@RequiredArgsConstructor
public class JwtAuthenticationProvider {

    private String secretKey = "secret";

    private long tokenValidTime = 1000L * 60 * 60;

    @Autowired
    private UserService userService;

    // JWT 토큰 생성
    public String createToken(String userPk, List<String> roles) {
        Claims claims = Jwts.claims().setSubject(userPk); // JWT payload 에 저장되는 정보단위
        claims.put("roles", roles); // 정보는 key / value 쌍으로 저장된다.
        Date now = new Date();
        return Jwts.builder()
                .setClaims(claims) // 정보 저장
                .setIssuedAt(now) // 토큰 발행 시간 정보
                .setExpiration(new Date(now.getTime() + tokenValidTime)) // set Expire Time
                .signWith(SignatureAlgorithm.HS256, secretKey)  // 사용할 암호화 알고리즘과
                // signature 에 들어갈 secret값 세팅
                .compact();
    }

    // JWT 토큰에서 인증 정보 조회
    public Authentication getAuthentication(String token) {
        User user = userService.loadUserByUsername(this.getUserPk(token));
        return new UsernamePasswordAuthenticationToken(user, "", user.getAuthorities());
    }

    // 토큰에서 회원 정보 추출
    public String getUserPk(String token) {
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
    }

    // Request의 Header에서 token 값을 가져옵니다. "X-AUTH-TOKEN" : "TOKEN값'
    public String resolveToken(HttpServletRequest request) {
        String token = null;
        Cookie cookie = WebUtils.getCookie(request, "X-AUTH-TOKEN");
        if(cookie != null) token = cookie.getValue();
        return token;
    }

    // 토큰의 유효성 + 만료일자 확인
    public boolean validateToken(String jwtToken) {
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken);
            return !claims.getBody().getExpiration().before(new Date());
        } catch (Exception e) {
            return false;
        }
    }
}
トークンの暗号解読プロセスや有効期限の確認などの機能を書いてから適用します.
そしてここで終わるのではなく、フィルターでマウントします.
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtAuthenticationProvider jwtAuthenticationProvider;

    public JwtAuthenticationFilter(JwtAuthenticationProvider provider) {
        jwtAuthenticationProvider = provider;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = jwtAuthenticationProvider.resolveToken(request);

        if(token != null && jwtAuthenticationProvider.validateToken(token)){
            Authentication authentication = jwtAuthenticationProvider.getAuthentication(token);

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }
}
もしそうなら.また来ます.Security設定セクションで次の変更を行います.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private JwtAuthenticationProvider jwtAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors().and()
                .csrf().disable()
                .formLogin().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(new JwtAuthenticationFilter(jwtAuthenticationProvider), UsernamePasswordAuthenticationFilter.class);
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


}
そうすれば、コントローラに行って登録部分を処理すればいいのです.
  @PostMapping("/v1/user/login")
    @JsonProperty("requestDto")
    @ApiOperation(value = "로그인")
    public UserLoginResponseDto login(@RequestBody UserLoginRequestDto requestDto,HttpServletResponse response ){
       User user= userService.findPasswordById(requestDto);
       if(user==null){
           throw new IllegalArgumentException("잘못된 계정정보입니다.");
       }
        System.out.println("여기까지됨123" + user.getUsername() + user.getRoles());
        String token = jwtAuthenticationProvider.createToken(user.getUsername(), user.getRoles());
        response.setHeader("X-AUTH-TOKEN", token);

        Cookie cookie = new Cookie("X-AUTH-TOKEN", token);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setSecure(true);
        response.addCookie(cookie);

        return new UserLoginResponseDto(user);
    }
また、ログアウト部分を設定することもできます.
    @PostMapping("/v1/user/logout")
    @ApiOperation(value = "로그아웃")
    public void logout(HttpServletResponse response){
        Cookie cookie = new Cookie("X-AUTH-TOKEN", null);
        cookie.setHttpOnly(true);
        cookie.setSecure(false);
        cookie.setMaxAge(0);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
タグを使用してページ情報クエリーコントローラを作成します
  @GetMapping("/v1/user/info")
    @ApiOperation(value = "마이페이지토큰이용")
    public UserResponseDto getInfo(){
 
       Object details = SecurityContextHolder.getContext().getAuthentication();
      if(details == null) {
            System.out.println("비어있음");
        }
        else {
            System.out.println("안비어있어욤");
            System.out.println(details);
        }
        if(details != null && !(details instanceof  String)) return new UserLoginResponseDto((User) details);
 

    }
このようにして作成してSwagerに移動して確認しておきます

さっき安全措置で言った部分がいいです.

情報がこんなによく出ている.
ここでテストできますが、postmanに移動してテストを行うと...



登録してログインすると、

うん.何も変わってないの?
リクエストで受け取ったタイトルを見たら

そのまま受け取りました.では.
これを持って検索するために、私は大きな値を保存しました.

問い合わせたら...

出てこない...
フィルタリングプロセスに関連する部分が問題のようです.だからこの部分を理解するために.
自らfilterの役を演じることにした.Controllerの情報セクションを変更しました
    @GetMapping("/v1/user/info")
    @ApiOperation(value = "마이페이지토큰이용")
    public UserResponseDto getInfo(HttpServletRequest request){
        System.out.println("Zzz");

        System.out.println(request.getHeader("X-AUTH-TOKEN") + "^.^");  // 토큰값봐보기
        String token = request.getHeader("X-AUTH-TOKEN");  //토큰 헤더에서 직접가져오기
        System.out.println(token+ "^.^");
        String userpk = jwtAuthenticationProvider.getUserPk(token); //토큰으로 아이디값조회
        System.out.println(userpk + " sss");
        // Object details = SecurityContextHolder.getContext().getAuthentication(); 
       /* if(details == null) {
            System.out.println("비어있음");
        }
        else {
            System.out.println("안비어있어욤");
            System.out.println(details);
        }
        if(details != null && !(details instanceof  String)) return new UserLoginResponseDto((User) details);

        */
        System.out.println("반환값없음");
        return userService.findById(userpk); //아이디값으로 조회한 결과반환
    }
こうして...呜呜...フィルターを使ったらもったいない
それからまた調べて...

よく撮れました...
このようにトークンとセキュリティ設定を使用しています...バックエンド・アイテムを次に行う場合は、refreshとaccessを使用して他のフィルタを適用する必要があります.
残りの記事ではjenkinsによるec 2自動構築&導入を行います.