Spring Boot 통합 Spring Security 의 예제 코드

11049 단어 SpringBootSecurity
본 고 는 Spring Boot 통합 Spring Security 가 방법 적 으로 주 해 를 사용 하여 권한 제 어 를 실현 하고 사용자 정의 UserDetailService 를 사용 하여 MySQL 에서 사용자 정 보 를 불 러 오 는 것 을 설명 한다.Security 자체 MD5 암호 화 를 사용 하여 사용자 암 호 를 암호 화 합 니 다.페이지 템 플 릿 은 thymeleaf 엔진 을 사용 합 니 다.
원본 주소:https://github.com/li5454yong/springboot-security.git
1.pom 의존 도입

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.4.RELEASE</version>
 </parent>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.security.oauth</groupId>
   <artifactId>spring-security-oauth2</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.34</version>
  </dependency>
  <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.0.15</version>
  </dependency>
 </dependencies>
druid 연결 탱크,Spring Data Jpa 를 사용 하여 데이터베이스 접근 을 실현 합 니 다.
2.Spring Security 설정

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//  security  
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Bean
 @Override
 protected AuthenticationManager authenticationManager() throws Exception {
  return super.authenticationManager();
 }

 @Override
 protected void configure(HttpSecurity http) throws Exception {
  //        "/" "/home"
  http.authorizeRequests()
    .antMatchers("/", "/home").permitAll()
    //             
    .anyRequest().authenticated()
    .and()
    .formLogin()
    //      "/login"
    .loginPage("/login")
    .defaultSuccessUrl("/hello")//          "/hello"
    .permitAll()
    .and()
    .logout()
    .logoutSuccessUrl("/home")//        url "/home"
    .permitAll();
 }

 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth
   .userDetailsService(customUserDetailsService())
   .passwordEncoder(passwordEncoder());

 }

 /**
  *             MD5  
  * @return
  */
 @Bean
 public Md5PasswordEncoder passwordEncoder() {
  return new Md5PasswordEncoder();
 }

 /**
  *    UserDetailsService,           
  * @return
  */
 @Bean
 public CustomUserDetailsService customUserDetailsService(){
  return new CustomUserDetailsService();
 }
}
로그 인 url,로그 인 성공 후 점프 하 는 url,종료 후 점프 하 는 url 만 기본 설정 되 어 있 습 니 다.@EnableGlobalMethodSecurity(prePost Enabled=true)라 는 주 해 를 사용 하면 security 의 주 해 를 열 수 있 습 니 다.제어 권한 이 필요 한 방법 에@PreAuthorize,@PreFilter 라 는 주 해 를 사용 할 수 있 습 니 다.
3.사용자 정의 userDetailService

public class CustomUserDetailsService implements UserDetailsService {
 @Autowired //      
 private SUserService suserService;

 @Override
 public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
  //SUser          ,            ,    
  //    SUser  email     :
  SUser user = suserService.findUserByEmail(userName); 

  if (user == null) {

   throw new UsernameNotFoundException("UserName " + userName + " not found");

  }

  // SecurityUser  UserDetails  SUser Email   username
  SecurityUser securityUser = new SecurityUser(user);
  Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
  authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
  return securityUser; 

 }

}
UserDetailsService 인 터 페 이 스 를 실현 하고 loadUserByUsername 방법 을 다시 써 서 데이터베이스 에서 사용자 정 보 를 꺼 내야 합 니 다.마지막 으로 UserDetails 실현 클래스 를 되 돌려 줍 니 다.
4.오류 처리 설정 정의

@Configuration
public class ErrorPageConfig {
 @Bean
 public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
  return new MyCustomizer();
 }
 private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
  @Override
  public void customize(ConfigurableEmbeddedServletContainer container) {
   container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
  }
 }
}
접근 오류 가 발생 했 을 때"/403"으로 이동 합 니 다.
5.컨트롤 러 인터페이스

@Controller
public class IndexController {

 @Resource
 private SUserService sUserService;

 @RequestMapping("/home")
 public String home() {
  return "home";

 }


 @PreAuthorize("hasRole('user')")
 @RequestMapping(value = "/admin",method = RequestMethod.GET)
 public String toAdmin(){

  return "helloAdmin";
 }

 @RequestMapping("/hello")
 public String hello() {

  return "hello";

 }

 @RequestMapping("/login")
 public String login(){
  return "login";
 }

 @RequestMapping("/")
 public String root() {
  return "index";

 }

 @RequestMapping("/403")
 public String error(){
  return "403";
 }
}
toAdmin()방법 에@PreAuthorize("hasRole('user')")를 사용 하여 이 방법 에 접근 하려 면 user 역할 이 필요 하 다 는 뜻 입 니 다.권한 차원 에서 제어 하려 면@PreAuthorize('hasPermission()')를 사용 할 수 있 습 니 다.여 기 는 그 중의 한 가지 용법 만 사 용 했 을 뿐 더 많은 사용 방법 은 공식 문 서 를 볼 수 있다.주의해 야 할 것 은 Spring Security 의 기본 캐릭터 접 두 사 는"ROLE"입 니 다.hasRole 방법 을 사용 할 때 기본적으로 추가 되 었 기 때문에 데이터베이스 에 있 는 사용자 역할 은'ROLE'일 것 입 니 다.user",user 앞 에"ROLE "를 추가 합 니 다.접두사.
6.테스트
시작 항목,접근http://localhost:1130/login

로그 인 을 클릭 하여"/hello"에 입장

클릭 하여 관리자 페이지 로 이동

배경 에 있 는'/admin'이라는 url 에 대응 하 는 방법 에 있어 서 사용자 가 반드시'user'역할 을 해 야 한 다 는 것 을 제한 합 니 다.데이터베이스 에 도 로그 인 한 사용자 가 이 역할 을 가지 고 있 습 니 다.
현재 저 희 는 데이터베이스 에 있 는 사용자 역할 을 수정 하여"ROLE"로 바 꾸 었 습 니 다.admin”。로그 인 을 종료 하고 다시 로그 인 합 니 다.'관리자 페이지 로 가기'단 추 를 다시 누 르 면 다음 페이지 로 이동 합 니 다.
 
지금 은'user'권한 이 없어 서 방문 할 때 이상 을 던 졌 고 차단 당 한 후'/403'으로 재 설정 되 었 습 니 다.
7.POST 방식 접근,오류 코드 403
우선"/admin"을 POST 요청 으로 변경 합 니 다.

 @PreAuthorize("hasRole('user')")
 @RequestMapping(value = "/admin",method = RequestMethod.POST)
 public String toAdmin(){
  return "helloAdmin";
 }
"관리자 페이지 로 가기"단추 의 요청 방식 을 원래 form 에서 get 제출 을 표현 하고 ajax 방식 POST 로 변경 합 니 다.왜 form 의 POST 로 제출 하지 않 았 는 지 에 대해 서 는 나중에 말씀 드 리 겠 습 니 다.코드 수정

<body>

<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>

<!--<form th:action="@{/logout}" method="post">

 <input type="submit" value="Sign Out"/>
</form>
<form th:action="@{/admin}" method="get">
 <input th:type="submit" th:value="       "/>

</form>-->
<a th:href="@{/admin}" rel="external nofollow" >         </a>
<input th:type="submit" onclick="testPost()" th:value="       "/>
</body>
<script>
 function testPost() {
  $.ajax({
   url:"/admin",
   type:'POST',

   success:function (data) {

   }
  });
 }
</script>
"관리자 페이지 로 가기"단 추 를 누 르 면 디 버 깅 대 에서 다음 과 같이 볼 수 있 습 니 다.
 
이 는 프레임 내부 에서 CSRF(Cross-site request forgery 크로스 오 버 요청 위조)의 발생 을 방지 하고 get 을 제외 한 대부분의 방법 을 제 한 했 기 때문이다.
다음은 해결 방법:
우선 탭 에 다음 과 같은 내용 을 추가 합 니 다.

 <meta name="_csrf" th:content="${_csrf.token}"/>
 <meta name="_csrf_hader" th:content="${_csrf.headerName}"/>
이 token 을 추가 하면 배경 에서 이 token 의 정확성 을 검증 하고 정확 하면 post 접근 을 받 습 니 다.
그리고 ajax 코드 에 다음 코드 를 추가 합 니 다:

var token = $('meta[name="_csrf"]').attr("content");
var header = $('meta[name="_csrf_hader"]').attr("content");
$(document).ajaxSend(function(e,xhr,opt){
   xhr.setRequestHeader(header,token);
  });
이렇게 하면 POST,DELETE 등 다른 방식 으로 정상적으로 방문 할 수 있다.
위 에 서 는 폼 의 POST 방식 으로 제출 하 겠 다 고 했 는데 페이지 소스 코드 를 보면 볼 수 있 습 니 다.
 
프레임 워 크 는 form 폼 에 숨겨 진 도 메 인 을 자동 으로 삽입 합 니 다.value 값 은 바로 token 입 니 다.따라서 form 폼 으로 POST 요청 을 제출 하 는 것 은 직접 통과 할 수 있 습 니 다.ajax 방식 으로 제출 하려 면 그 코드 를 추가 해 야 합 니 다.
자,이 글 은 여기까지 입 니 다.그 다음 에 REST API 스타일 이 Spring Security 를 어떻게 사용 하여 권한 을 제어 하 는 지 에 대한 글 도 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기