详解Spring Boot 使用Spring security 集成CAS

网友投稿 781 2023-05-12


详解Spring Boot 使用Spring security 集成CAS

1.创建工程

创建Maven工程:springboot-security-cas

2.加入依赖

创建工程后,打开pom.xml,在pom.xml中加入以下内容:

org.springframework.boot

spring-boot-starter-parent

1.4.3.RELEASE

UTF-8

1.8

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-security

org.springframework.security

spring-security-cas

org.springframework.security

spring-security-taglibs

org.springframework.boot

spring-boot-devtools

true

org.springframework.boot

spring-boot-configuration-processor

true

org.springframework.boot

spring-boot-maven-plugin

3.创建application.properties

创建application.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('TEST')")//有TEST权限的才能访问

@RequestMapping("/security")

public String security() {

return "hello world security";

}

@PreAuthorize("hasAuthority('ADMIN')")//必须要有ADMIN权限的才能访问

@RequestMapping("/authorize")

public String authorize() {

return "有权限访问";

}

/**这里注意的是,TEST与ADMIN只是权限编码,可以自己定义一套规则,根据实http://际情况即可*/

}

5.创建Security配置类(SecurityConfig)

创建Security配置类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.AuthenticationUserDetailshttp://Service;

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 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,用于将properties文件指定的内容注入以方便使用,这里不注入也是可以的,可以获取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 authorities = new HashSet();

AuthorityInfo authorityInfo = new AuthorityInfo("TEST");

authorities.add(authorityInfo);

userInfo.setAuthorities(authorities);

return userInfo;

}*/

//实现AuthenticationUserDetailsService,实现loadUserDetails方法

implements AuthenticationUserDetailsService {

@Override

public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {

System.out.println("当前的用户名是:"+token.getName());

/*这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息*/

UserInfo userInfo = new UserInfo();

userInfo.setUsername("admin");

userInfo.setName("admin");

Set authorities = new HashSet();

AuthorityInfo authorityInfo = new AuthorityInfo("TEST");

authorities.add(authorityInfo);

userInfo.setAuthorities(authorities);

return userInfo;

}

}

(3)定义AuthorityInfo类,用于加载当前登录用户的权限信息,实现GrantedAuthority接口,代码如下:

package com.chengli.springboot.custom;

import org.springframework.security.core.GrantedAuthoritblqExEyIy;

/**

* 权限信息

*

* @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 authorities = new HashSet();

....省略getters setters 方法

}

到这里基本就已经完成了,运行CAS Server ,将以上的application.properties文件中的地址修改为实际的地址即可运行。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java根据Request获取客户端IP
下一篇:隐式实现接口(隐式接口和显示接口)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~