Spring/SpringBoot

Spring Boot으로 웹 출시까지 #12. 권한에 맞는 화면 구성 및 API 호출 & 13. JPA 이용한 커스텀 쿼리 만들기

느리지만 꾸준하게 2022. 6. 6. 18:39

 

  • 사용자 권한에 따라 API 제한 하기

 

  • @Secured, @RolesAllowed, @PreAuthorize 혹은 새로운 어노테이션을 만들어서 접근 권한을 설정

 

  • 가장 간단한 @Secured를 이용

 

 

 

WebSecurityConfig Class에서

아래 부분에서 @Autowired를 주석처리 해주니 일단 에러가 임시방편으로 해결되었다. 근데 Signup하고 signin이 되는 과정으로 안넘어간다.

jay2로 회원가입을 하고 DB를 확인하면 아래와 같다.

 

 

로그인이 안되는중 => 게시판도 안보임.

MySQL [mydb]> select * from user;
+----+----------+--------------------------------------------------------------+---------+
| id | username | password                                                     | enabled |
+----+----------+--------------------------------------------------------------+---------+
|  1 | 123      | $2a$10$3fDRmrPw3cTXkoqVAAxJHuodLjGmoomE0H3M.EQ2JhAOd557en0qS |        |
|  2 | jay      | $2a$10$RX26X82gLUXB94x34kAzferlwOyTUZCGYei001r0cF0twjWZcrWkC |        |
|  4 | jay2     | $2a$10$/hAEnsKU4EilNv9LtS3kl.dXke0h8XPAmmBp08kDiIMj3ZgQPZWqu |        |
+----+----------+--------------------------------------------------------------+---------+
3 rows in set (0.002 sec)
MySQL [mydb]> INSERT INTO role (id, name) VALUES(2, 'ROLE_ADMIN');
Query OK, 1 row affected (0.002 sec)

MySQL [mydb]> select * from role;
+----+------------+
| id | name       |
+----+------------+
|  1 | ROLE_USER  |
|  2 | ROLE_ADMIN |
+----+------------+
2 rows in set (0.000 sec)

 

 

Using generated security password: cd4cc291-447f-4f6a-8c59-e6d30474ed57

This generated password is for development use only. Your security configuration must be updated before running your application in production.

 

 

  • @Autowired 주석을 생략해서 에러를 임시방편으로 해결(circular reference => 순환참조 문제,,,,)
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'webSecurityConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?
//    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(passwordEncoder())
                .usersByUsernameQuery("select username, password, enabled "
                        + "from user "
                        + "where username = ?")
                .authoritiesByUsernameQuery("select u.username, r.name "
                        + "from user_role ur inner join user u on ur.user_id = u.id "
                        + "inner join role r on ur.role_id = r.id "
                        + "where u.username = ?");
    }

 

 

 

package com.example.myhome.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "/account/register", "/css/**", "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/account/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

//    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(passwordEncoder())
                .usersByUsernameQuery("select username, password, enabled "
                        + "from user "
                        + "where username = ?")
                .authoritiesByUsernameQuery("select u.username, r.name "
                        + "from user_role ur inner join user u on ur.user_id = u.id "
                        + "inner join role r on ur.role_id = r.id "
                        + "where u.username = ?");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

 

 

나중에 취소 삭제 확인 버튼이 각각 보이는 게시판이 나오게 하자. 

thymeleaf 사이트에서  Literal substitutions 참고

 

 

 

 

 

13:48

spring boot role annotation 참고

 

MethodSecurityConfig Class 참고

package com.example.myhome.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

@Configuration
@EnableGlobalMethodSecurity(
        prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
public class MethodSecurityConfig
        extends GlobalMethodSecurityConfiguration {
}

 

 

 

BoardApiController에서 ADMIN 사용자만 delete를 호출할 수 있도록 해준다.

@Secured("ROLE_ADMIN")
@DeleteMapping("/boards/{id}")
void deleteBoard(@PathVariable Long id) {
    repository.deleteById(id);
}

 

 

 

 

Spring Boot으로 웹 출시까지 #13. JPA 이용한 커스텀 쿼리 만들기

 

spring.io 사이트 참고

 

 

UserRepository Interface에 넣어준다.

package com.example.myhome.repository;

import com.example.myhome.model.Board;
import com.example.myhome.model.User;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {
    @EntityGraph(attributePaths = { "boards" })
    List<User> findAll();

    User findByUsername(String username);

    @Query("select u from User u where u.username like %?1%")
    List<User> findByUsernameQuery(String firstname);
}

 

 

 

아래와 같이 postman으로 데이터를 가져와본다.

localhost:8080/api/users/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

< 참고 :Spring Boot으로 웹 출시까지 #12. 권한에 맞는 화면 구성 및 API 호출>

https://www.youtube.com/watch?v=VuOydiUpHwk&list=PLPtc9qD1979DG675XufGs0-gBeb2mrona&index=13