GVKun编程网logo

使用Android和iOS的Spring Boot Rest Security(安卓 spring boot)

16

在本文中,我们将为您详细介绍使用Android和iOS的SpringBootRestSecurity的相关知识,并且为您解答关于安卓springboot的疑问,此外,我们还会提供一些关于2.Sprin

在本文中,我们将为您详细介绍使用Android和iOS的Spring Boot Rest Security的相关知识,并且为您解答关于安卓 spring boot的疑问,此外,我们还会提供一些关于2. Spring Boot的Spring Security认证过程、8. Spring Boot中Spring Security Session管理、java – 在Spring Boot中禁用@WebMvcTest的Spring Security配置类、Java-Springboot - 集成 spring-security 简单示例 (Version-springboot-2-1-3-RELEASE的有用信息。

本文目录一览:

使用Android和iOS的Spring Boot Rest Security(安卓 spring boot)

使用Android和iOS的Spring Boot Rest Security(安卓 spring boot)

我正在开发 spring rest网络服务 ,我的客户是 androidios 应用程序。问题是我的应用程序是
基于100%api的 ,即使是管理员也没有网站,所有内容都是移动的,我一直在努力仅使用api 进行 身份验证和授权
。在我的客户是浏览器之前,我做了一些小型的Spring项目。但是现在我已经呆了一个星期,而且我似乎找不到有关如何执行身份验证和授权的任何信息。是我的方法还是如此不寻常的事情。我将不胜感激任何帮助。谢谢

答案1

小编典典

您可以使用基本身份验证或摘要身份验证

https://docs.spring.io/spring-
security/site/docs/3.0.x/reference/basic.html

但是您应该小心,不要将其与HTTP一起使用,而只能与HTTPS一起使用,因为基本身份验证会将密码作为纯文本传输。

第二种方法是使用JWT保护您的应用程序。这是使用JWT的示例https://github.com/szerhusenBC/jwt-spring-
security-demo

2. Spring Boot的Spring Security认证过程

2. Spring Boot的Spring Security认证过程

类图

为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类

http://dandandeshangni.oss-cn-beijing.aliyuncs.com/github/Spring%20Security/core-classdiagram.png

概述

核心验证器

AuthenticationManager

该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数;

org.springframework.security.authentication.AuthenticationManager

public interface AuthenticationManager {
	Authentication authenticate(Authentication authentication)
			throws AuthenticationException;
}

ProviderManager

org.springframework.security.authentication.ProviderManager

它是 AuthenticationManager 的一个实现类,提供了基本的认证逻辑和方法;它包含了一个 List<AuthenticationProvider> 对象,通过 AuthenticationProvider 接口来扩展出不同的认证提供者(当Spring Security默认提供的实现类不能满足需求的时候可以扩展AuthenticationProvider 覆盖supports(Class<?> authentication) 方法);

验证逻辑

AuthenticationManager 接收 Authentication 对象作为参数,并通过 authenticate(Authentication)方法对其进行验证;AuthenticationProvider实现类用来支撑对 Authentication 对象的验证动作;UsernamePasswordAuthenticationToken实现了 Authentication主要是将用户输入的用户名和密码进行封装,并供给 AuthenticationManager 进行验证;验证完成以后将返回一个认证成功的 Authentication 对象;

 

Authentication

org.springframework.security.core.Authentication

Authentication对象中的主要方法

public interface Authentication extends Principal, Serializable {
	//#1.权限结合,可使用AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_ADMIN")返回字符串权限集合
	Collection<? extends GrantedAuthority> getAuthorities();
	//#2.用户名密码认证时可以理解为密码
	Object getCredentials();
	//#3.认证时包含的一些信息。
	Object getDetails();
	//#4.用户名密码认证时可理解时用户名
	Object getPrincipal();
	//#5.是否被认证,认证为true	
	boolean isAuthenticated();
	//#6.设置是否能被认证
	void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

ProviderManager

org.springframework.security.authentication.ProviderManager

ProviderManagerAuthenticationManager的实现类,提供了基本认证实现逻辑和流程;

public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		//#1.获取当前的Authentication的认证类型
		Class<? extends Authentication> toTest = authentication.getClass();
		AuthenticationException lastException = null;
		Authentication result = null;
		boolean debug = logger.isDebugEnabled();
		//#2.遍历所有的providers使用supports方法判断该provider是否支持当前的认证类型,不支持的话继续遍历
		for (AuthenticationProvider provider : getProviders()) {
			if (!provider.supports(toTest)) {
				continue;
			}

			if (debug) {
				logger.debug("Authentication attempt using "
						+ provider.getClass().getName());
			}

			try {
				//#3.支持的话调用provider的authenticat方法认证
				result = provider.authenticate(authentication);

				if (result != null) {
					//#4.认证通过的话重新生成Authentication对应的Token
					copyDetails(authentication, result);
					break;
				}
			}
			catch (AccountStatusException e) {
				prepareException(e, authentication);
				// SEC-546: Avoid polling additional providers if auth failure is due to
				// invalid account status
				throw e;
			}
			catch (InternalAuthenticationServiceException e) {
				prepareException(e, authentication);
				throw e;
			}
			catch (AuthenticationException e) {
				lastException = e;
			}
		}

		if (result == null && parent != null) {
			// Allow the parent to try.
			try {
				//#5.如果#1 没有验证通过,则使用父类型AuthenticationManager进行验证
				result = parent.authenticate(authentication);
			}
			catch (ProviderNotFoundException e) {
				// ignore as we will throw below if no other exception occurred prior to
				// calling parent and the parent
				// may throw ProviderNotFound even though a provider in the child already
				// handled the request
			}
			catch (AuthenticationException e) {
				lastException = e;
			}
		}
		//#6. 是否擦出敏感信息
		if (result != null) {
			if (eraseCredentialsAfterAuthentication
					&& (result instanceof CredentialsContainer)) {
				// Authentication is complete. Remove credentials and other secret data
				// from authentication
				((CredentialsContainer) result).eraseCredentials();
			}

			eventPublisher.publishAuthenticationSuccess(result);
			return result;
		}

		// Parent was null, or didn''t authenticate (or throw an exception).

		if (lastException == null) {
			lastException = new ProviderNotFoundException(messages.getMessage(
					"ProviderManager.providerNotFound",
					new Object[] { toTest.getName() },
					"No AuthenticationProvider found for {0}"));
		}

		prepareException(lastException, authentication);

		throw lastException;
	}
  1. 遍历所有的 Providers,然后依次执行该 Provider 的验证方法
    • 如果某一个 Provider 验证成功,则跳出循环不再执行后续的验证;
    • 如果验证成功,会将返回的 result 既 Authentication 对象进一步封装为 Authentication Token; 比如 UsernamePasswordAuthenticationToken、RememberMeAuthenticationToken 等;这些 Authentication Token 也都继承自 Authentication 对象;
  2. 如果 #1 没有任何一个 Provider 验证成功,则试图使用其 parent Authentication Manager 进行验证;
  3. 是否需要擦除密码等敏感信息;

 

AuthenticationProvider

org.springframework.security.authentication.AuthenticationProvider

ProviderManager 通过 AuthenticationProvider 扩展出更多的验证提供的方式;而 AuthenticationProvider 本身也就是一个接口,从类图中我们可以看出它的实现类AbstractUserDetailsAuthenticationProvider AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider DaoAuthenticationProvider Spring Security中一个核心的Provider,对所有的数据库提供了基本方法和入口。

 

DaoAuthenticationProvider

org.springframework.security.authentication.dao.DaoAuthenticationProvider

DaoAuthenticationProvider主要做了以下事情

  1. 对用户身份尽心加密操作;
     #1.可直接返回BCryptPasswordEncoder,也可以自己实现该接口使用自己的加密算法核心方法String encode(CharSequence rawPassword);和boolean matches(CharSequence rawPassword, String encodedPassword);
    private PasswordEncoder passwordEncoder;
    
  2. 实现了 AbstractUserDetailsAuthenticationProvider 两个抽象方法,
    1. 获取用户信息的扩展点
      protected final UserDetails retrieveUser(String username,
           UsernamePasswordAuthenticationToken authentication)
           throws AuthenticationException {
       UserDetails loadedUser;
      
       try {
           loadedUser = this.getUserDetailsService().loadUserByUsername(username);
       }
      

      主要是通过注入UserDetailsService接口对象,并调用其接口方法 loadUserByUsername(String username) 获取得到相关的用户信息。UserDetailsService接口非常重要。

    2. 实现 additionalAuthenticationChecks 的验证方法(主要验证密码);

 

AbstractUserDetailsAuthenticationProvider

org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider

AbstractUserDetailsAuthenticationProviderDaoAuthenticationProvider提供了基本的认证方法;

public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
				messages.getMessage(
						"AbstractUserDetailsAuthenticationProvider.onlySupports",
						"Only UsernamePasswordAuthenticationToken is supported"));

		// Determine username
		String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
				: authentication.getName();

		boolean cacheWasUsed = true;
		UserDetails user = this.userCache.getUserFromCache(username);

		if (user == null) {
			cacheWasUsed = false;

			try {
				//#1.获取用户信息由子类实现即DaoAuthenticationProvider
				user = retrieveUser(username,
						(UsernamePasswordAuthenticationToken) authentication);
			}
			catch (UsernameNotFoundException notFound) {
				logger.debug("User ''" + username + "'' not found");

				if (hideUserNotFoundExceptions) {
					throw new BadCredentialsException(messages.getMessage(
							"AbstractUserDetailsAuthenticationProvider.badCredentials",
							"Bad credentials"));
				}
				else {
					throw notFound;
				}
			}

			Assert.notNull(user,
					"retrieveUser returned null - a violation of the interface contract");
		}

		try {
			//#2.前检查由DefaultPreAuthenticationChecks类实现(主要判断当前用户是否锁定,过期,冻结User接口)
			preAuthenticationChecks.check(user);
			//#3.子类实现
			additionalAuthenticationChecks(user,
					(UsernamePasswordAuthenticationToken) authentication);
		}
		catch (AuthenticationException exception) {
			if (cacheWasUsed) {
				// There was a problem, so try again after checking
				// we''re using latest data (i.e. not from the cache)
				cacheWasUsed = false;
				user = retrieveUser(username,
						(UsernamePasswordAuthenticationToken) authentication);
				preAuthenticationChecks.check(user);
				additionalAuthenticationChecks(user,
						(UsernamePasswordAuthenticationToken) authentication);
			}
			else {
				throw exception;
			}
		}
		//#4.检测用户密码是否过期对应#2 的User接口
		postAuthenticationChecks.check(user);

		if (!cacheWasUsed) {
			this.userCache.putUserInCache(user);
		}

		Object principalToReturn = user;

		if (forcePrincipalAsString) {
			principalToReturn = user.getUsername();
		}

		return createSuccessAuthentication(principalToReturn, authentication, user);
	}

AbstractUserDetailsAuthenticationProvider主要实现了AuthenticationProvider的接口方法 authenticate 并提供了相关的验证逻辑;

  1. 获取用户返回UserDetails AbstractUserDetailsAuthenticationProvider定义了一个抽象的方法
    protected abstract UserDetails retrieveUser(String username,
      UsernamePasswordAuthenticationToken authentication)
      throws AuthenticationException;
    
  2. 三步验证工作
    1. preAuthenticationChecks
    2. additionalAuthenticationChecks(抽象方法,子类实现)
    3. postAuthenticationChecks
  3. 将已通过验证的用户信息封装成 UsernamePasswordAuthenticationToken 对象并返回;该对象封装了用户的身份信息,以及相应的权限信息,相关源码如下,
    protected Authentication createSuccessAuthentication(Object principal,
         UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
                 principal, authentication.getCredentials(),
                 authoritiesMapper.mapAuthorities(user.getAuthorities()));
         result.setDetails(authentication.getDetails());
    
         return result;
     }

 

UserDetailsService 

org.springframework.security.core.userdetails.UserDetailsService

  1. UserDetailsService是一个接口,提供了一个方法

    public interface UserDetailsService {
     UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }
    

    通过用户名 username 调用方法 loadUserByUsername 返回了一个UserDetails接口对象(对应AbstractUserDetailsAuthenticationProvider的三步验证方法);

    public interface UserDetails extends Serializable {
     #1.权限集合
     Collection<? extends GrantedAuthority> getAuthorities();
     #2.密码	
     String getPassword();
     #3.用户民
     String getUsername();
     #4.用户是否过期
     boolean isAccountNonExpired();
     #5.是否锁定	
     boolean isAccountNonLocked();
     #6.用户密码是否过期	
     boolean isCredentialsNonExpired();
     #7.账号是否可用(可理解为是否删除)
     boolean isEnabled();
    }
    

Spring 为UserDetailsService默认提供了一个实现类 org.springframework.security.core.userdetails.jdbc.JdbcDaoImp

 

JdbcUserDetailsManager

org.springframework.security.provisioning.JdbcUserDetailsManager

该实现类主要是提供基于JDBC对 User 进行增、删、查、改的方法

public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager,
		GroupManager {
	// ~ Static fields/initializers
	// =====================================================================================

	// UserDetailsManager SQL
	#1.定义了一些列对数据库操作的语句
	public static final String DEF_CREATE_USER_SQL = "insert into users (username, password, enabled) values (?,?,?)";
	public static final String DEF_DELETE_USER_SQL = "delete from users where username = ?";
	public static final String DEF_UPDATE_USER_SQL = "update users set password = ?, enabled = ? where username = ?";
	public static final String DEF_INSERT_AUTHORITY_SQL = "insert into authorities (username, authority) values (?,?)";
	public static final String DEF_DELETE_USER_AUTHORITIES_SQL = "delete from authorities where username = ?";
	public static final String DEF_USER_EXISTS_SQL = "select username from users where username = ?";
	public static final String DEF_CHANGE_PASSWORD_SQL = "update users set password = ? where username = ?";

 

InMemoryUserDetailsManager

org.springframework.security.provisioning.InMemoryUserDetailsManager

该实现类主要是提供基于内存对 User 进行增、删、查、改的方法 `public class InMemoryUserDetailsManager implements UserDetailsManager { protected final Log logger = LogFactory.getLog(getClass()); #1.用MAP 存储 private final Map<String, MutableUserDetails> users = new HashMap<String, MutableUserDetails>();

private AuthenticationManager authenticationManager;

public InMemoryUserDetailsManager() {
}

public InMemoryUserDetailsManager(Collection<UserDetails> users) {
	for (UserDetails user : users) {
		createUser(user);
	}
}`

总结

UserDetailsService接口作为桥梁,是DaoAuthenticationProvier与特定用户信息来源进行解耦的地方,UserDetailsServiceUserDetailsUserDetailsManager所构成;UserDetailsUserDetailsManager各司其责,一个是对基本用户信息进行封装,一个是对基本用户信息进行管理;

特别注意UserDetailsServiceUserDetails以及UserDetailsManager都是可被用户自定义的扩展点,我们可以继承这些接口提供自己的读取用户来源和管理用户的方法,比如我们可以自己实现一个 与特定 ORM 框架,比如 Mybatis 或者 Hibernate,相关的UserDetailsServiceUserDetailsManager

 

时序图

http://dandandeshangni.oss-cn-beijing.aliyuncs.com/github/Spring%20Security/core-service-Sequence.png

8. Spring Boot中Spring Security Session管理

8. Spring Boot中Spring Security Session管理

用户登录成功后,信息保存在服务器Session中,这节学习下如何管理这些Session。这节将在Spring Security短信验证码登录的基础上继续扩展。

Session超时设置

Session超时时间也就是用户登录的有效时间。要设置Session超时时间很简单,只需要在配置文件中添加:

server:
  servlet:
    session:
      timeout: 3600

单位为秒,通过上面的配置,Session的有效期为一个小时。

值得注意的是,Session的最小有效期为60秒,也就是说即使你设置为小于60秒的值,其有效期还是为60秒。查看

TomcatServletWebServerFactory 的源码即可发现原因:

org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory

Session失效后,刷新页面后将跳转到认证页面,我们可以再添加一些配置,自定义Session失效后的一些行为。

在Spring Security中配置Session管理器,并配置Session失效后要跳转的URL:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
                .formLogin() // 表单登录
                .loginPage("/authentication/require") // 登录跳转 URL
                .loginProcessingUrl("/login") // 处理表单登录 URL
                .successHandler(authenticationSucessHandler)//处理登录成功
                .failureHandler(authenticationFailureHandler)//处理登录失败
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
                .tokenValiditySeconds(3600) // remember 过期时间,单为秒
                .userDetailsService(userDetailService) // 处理自动登录逻辑
                .and()
                .authorizeRequests() // 授权配置
                .antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
                .anyRequest()  // 所有请求
                .authenticated() // 都需要认证
                .and()
                .sessionManagement() // 添加 Session管理器
                .invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
                .and().csrf().disable()
                .apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
    }

上面配置了Session失效后跳转到/session/invalid,并且将这个URL添加到了免认证路径中。

在Controller里添加一个方法,映射该请求:

@GetMapping("/session/invalid")
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String sessionInvalid(){
    return "session已失效,请重新认证";
}

我们将Session的超时时间设置为最小值60秒,重启项目,认证后等待60秒并刷新页面:

可看到请求跳转到了我们自定义的/session/invalidURL上。

 

Session并发控制

Session并发控制可以控制一个账号同一时刻最多能登录多少个。我们在Spring Security配置中继续添加Session相关配置:

    @Autowired
    private MySessionExpiredStrategy sessionExpiredStrategy;

  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
                .formLogin() // 表单登录
                .loginPage("/authentication/require") // 登录跳转 URL
                .loginProcessingUrl("/login") // 处理表单登录 URL
                .successHandler(authenticationSucessHandler)//处理登录成功
                .failureHandler(authenticationFailureHandler)//处理登录失败
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
                .tokenValiditySeconds(3600) // remember 过期时间,单为秒
                .userDetailsService(userDetailService) // 处理自动登录逻辑
                .and()
                .authorizeRequests() // 授权配置
                .antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
                .anyRequest()  // 所有请求
                .authenticated() // 都需要认证
                .and()
                .sessionManagement() // 添加 Session管理器
                .invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
                .maximumSessions(1)
                .expiredSessionStrategy(sessionExpiredStrategy)
                .and()
                .and().csrf().disable()
                .apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
    }

maximumSessions配置了最大Session并发数量为1个,如果mrbird这个账户登录后,在另一个客户端也使用mrbird账户登录,那么第一个使用mrbird登录的账户将会失效,类似于一个先入先出队列。expiredSessionStrategy配置了Session在并发下失效后的处理策略,这里为我们自定义的策略MySessionExpiredStrategy

MySessionExpiredStrategy实现SessionInformationExpiredStrategy


@Component
public class MySessionExpiredStrategy implements SessionInformationExpiredStrategy {

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
        HttpServletResponse response = event.getResponse();
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("您的账号已经在别的地方登录,当前登录已失效。如果密码遭到泄露,请立即修改密码!");
    }
}

为了演示这个效果,我们先将Session超时时间设置久一点,比如3600秒,然后重启项目,在Chrome里使用admin账户登录。

登录成功后,在firefox上也是用admin账户登录,登录成功后回到chrome,刷新页面,效果如下所示:

除了后者将前者踢出的策略,我们也可以控制当Session达到最大有效数的时候,不再允许相同的账户登录。

要实现这个功能只需要在上面的配置中添加:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加短信验证码校验过滤器
                .formLogin() // 表单登录
                .loginPage("/authentication/require") // 登录跳转 URL
                .loginProcessingUrl("/login") // 处理表单登录 URL
                .successHandler(authenticationSucessHandler)//处理登录成功
                .failureHandler(authenticationFailureHandler)//处理登录失败
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
                .tokenValiditySeconds(3600) // remember 过期时间,单为秒
                .userDetailsService(userDetailService) // 处理自动登录逻辑
                .and()
                .authorizeRequests() // 授权配置
                .antMatchers("/authentication/require", "/login.html", "/code/image","/code/sms","/session/invalid").permitAll() // 登录跳转 URL 无需认证
                .anyRequest()  // 所有请求
                .authenticated() // 都需要认证
                .and()
                .sessionManagement() // 添加 Session管理器
                .invalidSessionUrl("/session/invalid") // Session失效后跳转到这个链接
                .maximumSessions(1)
                .maxSessionsPreventsLogin(true)
                .expiredSessionStrategy(sessionExpiredStrategy)
                .and()
                .and().csrf().disable()
                .apply(smsAuthenticationConfig);// 将短信验证码认证配置加到 Spring Security 中
    }

重启系统,在chrome上登录admin账户后,在firefox上尝试使用admin账户登录:

可以看到登录受限。

 

java – 在Spring Boot中禁用@WebMvcTest的Spring Security配置类

java – 在Spring Boot中禁用@WebMvcTest的Spring Security配置类

最近我使用以下类将Spring Security添加到Spring Boot项目中:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig {
}

因此,默认情况下,我的所有URL现在都受到身份验证和自生密码的保护.

问题是我用于对控制器进行单元测试的@WebMvcTest类中的所有测试:

@RunWith(springrunner.class)
@WebMvcTest(SomeController.class)
public class SomeControllerTest {...}

由于缺乏授权,现在到处都失败了.

问题:我可以告诉@Test方法忽略授权,以便它们像以前一样继续成功吗?

如何防止在特定的@WebMvcTest单元测试类中选择@EnableWebSecurity配置类?

我希望已经存在的测试能够继续进行并稍后单独测试身份验证功能.

到目前为止,我已尝试在测试类中使用嵌套的配置类,以排除安全配置:

@RunWith(springrunner.class)
@WebMvcTest(SomeController.class)
public class SomeControllerTest {

    @Configuration
    @EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
    static class ContextConfiguration { }

 ....}

但似乎没有用.

注意:我使用的是Spring Boot 1.5.8

最佳答案
您可以在@WebMvcTest annoation中设置secure = false.
它将在您的测试中跳过Spring安全性mockmvc自动配置

@WebMvcTest(controllers = SomeController.class,secure = false)
public class SomeControllerTest {

Java-Springboot - 集成 spring-security 简单示例 (Version-springboot-2-1-3-RELEASE

Java-Springboot - 集成 spring-security 简单示例 (Version-springboot-2-1-3-RELEASE

  • 使用 Idea 的 Spring Initializr 或者 SpringBoot 官网下载 quickstart
  • 添加依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
  • 新建控制器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class UserController {
    @GetMapping("/user")
    public String getUsers() {
    return "Hello Spring Security";
    }
    }
  • logback.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="UTF-8"?>

    <configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file> 大专栏  Java-Springboot-集成spring-security简单示例(Version-springboot-2-1-3-RELEASE/data/www/file/logs/springboot.log</file>

    <encoder>
    <pattern>%date %d{HH: mm:ss.SSS} %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
    <pattern>%date %d{HH: mm:ss.SSS} %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
    </appender>

    <root level="debug">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
    </root>
    </configuration>
  • application.properties

    1
    2
    3
    # Server Domain-Port
    server.address=127.0.0.1
    server.port=9090
  • 启动 SpringBootApplication,springboot 已经和 spring-security 集成了,如果直接访问 http://localhost:9090/user 会跳到登陆页面,这是 spring-security 自带的,但是我们并没有创建任何用户啊,spring-security 有个默认的用户名 user,密码在控制台登陆页面

  • 默认密码在控制信息里,在控制台信息里搜索 Using generated,当然你的程序生成的密码肯定和我的不一样

    1
    Using generated security password: 6ae529ee-2281-4b66-8f30-b1ba0e7fec97
  • 使用用户名和密码登陆后:
    正常访问

  • 源码

今天关于使用Android和iOS的Spring Boot Rest Security安卓 spring boot的介绍到此结束,谢谢您的阅读,有关2. Spring Boot的Spring Security认证过程、8. Spring Boot中Spring Security Session管理、java – 在Spring Boot中禁用@WebMvcTest的Spring Security配置类、Java-Springboot - 集成 spring-security 简单示例 (Version-springboot-2-1-3-RELEASE等更多相关知识的信息可以在本站进行查询。

本文标签: