> Java > java지도 시간 > CAS 예제를 통합하기 위해 Spring Boot의 Spring 보안 사용 공유

CAS 예제를 통합하기 위해 Spring Boot의 Spring 보안 사용 공유

零下一度
풀어 주다: 2017-05-27 10:16:28
원래의
2922명이 탐색했습니다.

이 글은 CAS 통합을 위해 Spring 보안을 사용하는 Spring Boot에 대한 자세한 설명을 주로 소개하며, 관심 있는 친구들은 참고하시기 바랍니다

1. 프로젝트 만들기

Maven 프로젝트 생성: springboot-security-cas

2. 종속성 추가

프로젝트 생성 후, pom.xml을 열고 pom.xml에 다음 콘텐츠를 추가합니다.

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.4.3.RELEASE</version> 
  </parent> 
  <properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <java.version>1.8</java.version> 
  </properties> 
  <dependencies> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter</artifactId> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <!-- security starter Poms --> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-security</artifactId> 
    </dependency> 
    <!-- security 对CAS支持 --> 
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-cas</artifactId> 
    </dependency> 
    <!-- security taglibs --> 
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-taglibs</artifactId> 
    </dependency> 
    <!-- 热加载 --> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-devtools</artifactId> 
      <optional>true</optional> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-configuration-processor</artifactId> 
      <optional>true</optional> 
    </dependency> 
  </dependencies> 
  <build> 
    <plugins> 
      <plugin> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
    </plugins> 
  </build>
로그인 후 복사

3. application.properties 생성

애플리케이션 생성 .properties 파일에 다음 내용을 추가합니다:

#CAS服务地址 
cas.server.host.url=http://localhost:8081/cas 
#CAS服务登录地址 
cas.server.host.login_url=${cas.server.host.url}/login 
#CAS服务登出地址 
cas.server.host.logout_url=${cas.server.host.url}/logout?service=${app.server.host.url} 
#应用访问地址 
app.server.host.url=http://localhost:8080 
#应用登录地址 
app.login.url=/login 
#应用登出地址 
app.logout.url=/logout
로그인 후 복사

4. 입구 시작 클래스(MainConfig)를 생성합니다.

입구 시작 클래스 MainConfig를 만듭니다.

package com.chengli.springboot; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.security.access.prepost.PreAuthorize; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
@RestController 
@SpringBootApplication 
public class MainConfig { 
  public static void main(String[] args) { 
    SpringApplication.run(MainConfig.class, args); 
  } 
 
  @RequestMapping("/") 
  public String index() { 
    return "访问了首页哦"; 
  } 
 
  @RequestMapping("/hello") 
  public String hello() { 
    return "不验证哦"; 
  } 
 
  @PreAuthorize("hasAuthority(&#39;TEST&#39;)")//有TEST权限的才能访问 
  @RequestMapping("/security") 
  public String security() { 
    return "hello world security"; 
  } 
 
  @PreAuthorize("hasAuthority(&#39;ADMIN&#39;)")//必须要有ADMIN权限的才能访问 
  @RequestMapping("/authorize") 
  public String authorize() { 
    return "有权限访问"; 
  } 
   
  /**这里注意的是,TEST与ADMIN只是权限编码,可以自己定义一套规则,根据实际情况即可*/ 
}
로그인 후 복사

5. 보안 구성 클래스(SecurityConfig)를 생성합니다.

보안 구성 클래스 SecurityConfig를 생성합니다. :

package com.chengli.springboot.security; 
 
import org.jasig.cas.client.session.SingleSignOutFilter; 
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.security.cas.ServiceProperties; 
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken; 
import org.springframework.security.cas.authentication.CasAuthenticationProvider; 
import org.springframework.security.cas.web.CasAuthenticationEntryPoint; 
import org.springframework.security.cas.web.CasAuthenticationFilter; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
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.userdetails.AuthenticationUserDetailsService; 
import org.springframework.security.web.authentication.logout.LogoutFilter; 
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 
 
import com.chengli.springboot.custom.CustomUserDetailsService; 
import com.chengli.springboot.properties.CasProperties; 
 
@Configuration 
@EnableWebSecurity //启用web权限 
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
  @Autowired 
  private CasProperties casProperties; 
   
  /**定义认证用户信息获取来源,密码校验规则等*/ 
  @Override 
  protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    super.configure(auth); 
    auth.authenticationProvider(casAuthenticationProvider()); 
    //inMemoryAuthentication 从内存中获取 
    //auth.inMemoryAuthentication().withUser("chengli").password("123456").roles("USER") 
    //.and().withUser("admin").password("123456").roles("ADMIN"); 
     
    //jdbcAuthentication从数据库中获取,但是默认是以security提供的表结构 
    //usersByUsernameQuery 指定查询用户SQL 
    //authoritiesByUsernameQuery 指定查询权限SQL 
    //auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery(query).authoritiesByUsernameQuery(query); 
     
    //注入userDetailsService,需要实现userDetailsService接口 
    //auth.userDetailsService(userDetailsService); 
  } 
   
  /**定义安全策略*/ 
  @Override 
  protected void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests()//配置安全策略 
      //.antMatchers("/","/hello").permitAll()//定义/请求不需要验证 
      .anyRequest().authenticated()//其余的所有请求都需要验证 
      .and() 
    .logout() 
      .permitAll()//定义logout不需要验证 
      .and() 
    .formLogin();//使用form表单登录 
     
    http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint()) 
      .and() 
      .addFilter(casAuthenticationFilter()) 
      .addFilterBefore(casLogoutFilter(), LogoutFilter.class) 
      .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class); 
     
    //http.csrf().disable(); //禁用CSRF 
  } 
   
  /**认证的入口*/ 
  @Bean 
  public CasAuthenticationEntryPoint casAuthenticationEntryPoint() { 
    CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint(); 
    casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl()); 
    casAuthenticationEntryPoint.setServiceProperties(serviceProperties()); 
    return casAuthenticationEntryPoint; 
  } 
   
  /**指定service相关信息*/ 
  @Bean 
  public ServiceProperties serviceProperties() { 
    ServiceProperties serviceProperties = new ServiceProperties(); 
    serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl()); 
    serviceProperties.setAuthenticateAllArtifacts(true); 
    return serviceProperties; 
  } 
   
  /**CAS认证过滤器*/ 
  @Bean 
  public CasAuthenticationFilter casAuthenticationFilter() throws Exception { 
    CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter(); 
    casAuthenticationFilter.setAuthenticationManager(authenticationManager()); 
    casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl()); 
    return casAuthenticationFilter; 
  } 
   
  /**cas 认证 Provider*/ 
  @Bean 
  public CasAuthenticationProvider casAuthenticationProvider() { 
    CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider(); 
    casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService()); 
    //casAuthenticationProvider.setUserDetailsService(customUserDetailsService()); //这里只是接口类型,实现的接口不一样,都可以的。 
    casAuthenticationProvider.setServiceProperties(serviceProperties()); 
    casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator()); 
    casAuthenticationProvider.setKey("casAuthenticationProviderKey"); 
    return casAuthenticationProvider; 
  } 
   
  /*@Bean 
  public UserDetailsService customUserDetailsService(){ 
    return new CustomUserDetailsService(); 
  }*/ 
   
  /**用户自定义的AuthenticationUserDetailsService*/ 
  @Bean 
  public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService(){ 
    return new CustomUserDetailsService(); 
  } 
   
  @Bean 
  public Cas20ServiceTicketValidator cas20ServiceTicketValidator() { 
    return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl()); 
  } 
   
  /**单点登出过滤器*/ 
  @Bean 
  public SingleSignOutFilter singleSignOutFilter() { 
    SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter(); 
    singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl()); 
    singleSignOutFilter.setIgnoreInitConfiguration(true); 
    return singleSignOutFilter; 
  } 
   
  /**请求单点退出过滤器*/ 
  @Bean 
  public LogoutFilter casLogoutFilter() { 
    LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler()); 
    logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl()); 
    return logoutFilter; 
  } 
}
로그인 후 복사

6 .사용자 정의 클래스

(1) 편리한 사용을 위해 속성 파일에 지정된 내용을 삽입하는 CasProperties를 정의합니다. 여기에 인젝션하지 않는 것도 가능하며, 현재 Spring 환경을 얻을 수 있습니다.

package com.chengli.springboot.properties; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.stereotype.Component; 
 
/** 
 * CAS的配置参数 
 * @author ChengLi 
 */ 
@Component 
public class CasProperties { 
  @Value("${cas.server.host.url}") 
  private String casServerUrl; 
 
  @Value("${cas.server.host.login_url}") 
  private String casServerLoginUrl; 
 
  @Value("${cas.server.host.logout_url}") 
  private String casServerLogoutUrl; 
 
  @Value("${app.server.host.url}") 
  private String appServerUrl; 
 
  @Value("${app.login.url}") 
  private String appLoginUrl; 
 
  @Value("${app.logout.url}") 
  private String appLogoutUrl; 
......省略 getters setters 方法 
}
로그인 후 복사

(2) CustomUserDetailsService 클래스를 정의합니다.

package com.chengli.springboot.custom; 
 
import java.util.HashSet; 
import java.util.Set; 
 
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken; 
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
 
/** 
 * 用于加载用户信息 实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口 
 * @author ChengLi 
 * 
 */ 
public class CustomUserDetailsService /* 
  //实现UserDetailsService接口,实现loadUserByUsername方法 
  implements UserDetailsService { 
  @Override 
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
    System.out.println("当前的用户名是:"+username); 
    //这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息 
    UserInfo userInfo = new UserInfo(); 
    userInfo.setUsername("admin"); 
    userInfo.setName("admin"); 
    Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>(); 
    AuthorityInfo authorityInfo = new AuthorityInfo("TEST"); 
    authorities.add(authorityInfo); 
    userInfo.setAuthorities(authorities); 
    return userInfo; 
  }*/ 
   
   
  //实现AuthenticationUserDetailsService,实现loadUserDetails方法 
  implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> { 
 
  @Override 
  public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException { 
    System.out.println("当前的用户名是:"+token.getName()); 
    /*这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息*/ 
    UserInfo userInfo = new UserInfo(); 
    userInfo.setUsername("admin"); 
    userInfo.setName("admin"); 
    Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>(); 
    AuthorityInfo authorityInfo = new AuthorityInfo("TEST"); 
    authorities.add(authorityInfo); 
    userInfo.setAuthorities(authorities); 
    return userInfo; 
  } 
 
}
로그인 후 복사

(3) 현재 로그인한 사용자의 권한 정보를 로드하고 GrantedAuthority 인터페이스를 구현하는 데 사용되는 AuthorityInfo 클래스를 정의합니다. 코드는 다음과 같습니다.

package com.chengli.springboot.custom; 
 
import org.springframework.security.core.GrantedAuthority; 
 
/** 
 * 权限信息 
 * 
 * @author ChengLi 
 * 
 */ 
public class AuthorityInfo implements GrantedAuthority { 
  private static final long serialVersionUID = -175781100474818800L; 
 
  /** 
   * 权限CODE 
   */ 
  private String authority; 
 
  public AuthorityInfo(String authority) { 
    this.authority = authority; 
  } 
 
  @Override 
  public String getAuthority() { 
    return authority; 
  } 
 
  public void setAuthority(String authority) { 
    this.authority = authority; 
  } 
 
}
로그인 후 복사

(4) UserInfo를 정의합니다. 현재 사용자 정보를 로드하고 UserDetails 인터페이스를 구현하는 데 사용되는 클래스입니다. 코드는 다음과 같습니다.

package com.chengli.springboot.custom; 
 
import java.util.Collection; 
import java.util.HashSet; 
import java.util.Set; 
 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
 
/** 
 * 用户信息 
 * @、这里我写了几个较为常用的字段,id,name,username,password,可以根据实际的情况自己增加 
 * @author ChengLi 
 * 
 */ 
public class UserInfo implements UserDetails { 
  private static final long serialVersionUID = -1041327031937199938L; 
 
  /** 
   * 用户ID 
   */ 
  private Long id; 
 
  /** 
   * 用户名称 
   */ 
  private String name; 
 
  /** 
   * 登录名称 
   */ 
  private String username; 
 
  /** 
   * 登录密码 
   */ 
  private String password; 
 
  private boolean isAccountNonExpired = true; 
 
  private boolean isAccountNonLocked = true; 
 
  private boolean isCredentialsNonExpired = true; 
 
  private boolean isEnabled = true; 
 
  private Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>(); 
....省略getters setters 方法 
}
로그인 후 복사

CAS 서버를 실행하고 위의 주소를 애플리케이션에 추가합니다. 속성 파일을 실제 주소로 복사하여 실행합니다.

[관련 추천]

1. Bootstrap Table 사용 경험 요약

spring Aop을 사용한 비즈니스 구현에 대한 자세한 설명 레이어 mysql 읽기 및 쓰기 분리

3. Spring Boot는 MySQL 데이터베이스와 JPA 인스턴스의 샘플 코드 공유를 추가합니다

4. Restful 프로그램 개발을 위한 Spring Boot 튜토리얼

위 내용은 CAS 예제를 통합하기 위해 Spring Boot의 Spring 보안 사용 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿