spring cloud----spring Security

认证和授权

  认证:登录,验证用户名和密码

  授权:认证通过,给用户加上某些权限,这些权限控制用户是否可以访问资源服务器上哪些资源的资源

Spring Security

  我们自己实现用户登录过程中,spring MVC,需要自己写拦截器,验证用户是否登录,以及登录接口相关逻辑,当用户登录成功后,把用户信息放到session中等等。这些操作spring Security帮我们都完成了。sprint security提供了用户名和密码登录,退出,会话管理等认证功能,我们需要简单的配置就行。

  spring security给我们提供了要给简单的前台登录页面(用于测试),我们可以写自己的前台页面,然后post请求spring security的后台

OAuth2

  是一种协议:允许博客(第三方应用)访问微信上存放的我的个人信息,然后用这个信息来登录博客。

  客户端:浏览器,android,ios等

  资源拥有者:通常是用户,可以是应用程序,即资源的拥有者(比如我们自己)。资源拥有者需要通过客户端访问资源。

  授权服务器:(微信),我们自己搭建的授权服务器

  资源服务器:我们自己的服务器

  用户通过客户端访问微信,并且携带client_id(斗地主),让微信给斗地主授权,android拿到授权码,就去微信获取令牌,获取到令牌。就可以通过令牌访问斗地主了。

  用户通过客户端访问自己系统,并且携带client_id(自己的),让自己的授权服务给微博授权,客户端(浏览器)拿到授权码,就去自己授权服务获取令牌,获取到令牌。就可以通过令牌访问自己的资源服务器。

  授权服务和资源服务一般分布式系统是分开的,如果是单体应用,可是可以放到一起的。

  

Spring MVC+Spring Security

Spring Boot+Spring Security+jsp

  使用jsp,一定要在spring Boot中配置webapp/WEB-INF

  然后设置prefix和suffix

  spring security逻辑:登录页面post:localhost:port/login,调用loadUserByUsername(),等返回的对象保存到SecurityContextHolder中。结束。

Spring Boot+SpringCloud+Spring Security+jsp

  略

   

分析解释

配置:public void configure(ClientDetailsServiceConfigurer clients)

//类TokenEndpoint
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
    
        //会去找ClientDetail对象
	String clientId = getClientId(principal);
	ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);

}

配置:authorizedGrantTypes

clients.inMemory()
        //client模式
        .withClient("client_1")
        .authorizedGrantTypes("client_credentials", "refresh_token")//配置client_1有那些模式

当访问/oauth/token,会携带一个grant_type,spring security会去我们配置的模式["client_credentials", "refresh_token"]中找,看是否包含test,如果没有就报错,所以我们请求的grant_type必须是我们配置的type中的某一个。

授权码模式

说明:code

code会保存到authorizationCodeStore中【ConcurrentHashMap】

public class InMemoryAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {

	protected final ConcurrentHashMap<String, OAuth2Authentication> authorizationCodeStore = new ConcurrentHashMap<String, OAuth2Authentication>();

	@Override
	protected void store(String code, OAuth2Authentication authentication) {
		this.authorizationCodeStore.put(code, authentication);
	}

	@Override
	public OAuth2Authentication remove(String code) {
		OAuth2Authentication auth = this.authorizationCodeStore.remove(code);
		return auth;
	}

}

当调用验证授权码的时候,调用HashMap的remove方法。所以授权码只允许使用一次

//类RandomValueAuthorizationCodeServices	
public OAuth2Authentication consumeAuthorizationCode(String code)
			throws InvalidGrantException {
    OAuth2Authentication auth = this.remove(code);
    if (auth == null) {
        throw new InvalidGrantException("Invalid authorization code: " + code);
    }
    return auth;
}

请求/oauth/token,当指定了grant_type="authorization_code",必须传入一个code

Map<String, String> parameters = tokenRequest.getRequestParameters();
String authorizationCode = parameters.get("code");
String redirectUri = parameters.get(OAuth2Utils.REDIRECT_URI);

if (authorizationCode == null) {
  throw new InvalidRequestException("An authorization code must be supplied.");
}

SecurityContextHolder

  保存用户信息

SecurityContextHolder.getContext().getAuthentication();

PreAuthorize

  如果需要使用这个注解,需要在任意的@Configuration上添加@EnableGlobalMethodSecurity注解

  @PostAuthorize:调用方法之后拦截

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)//激活方法上的PreAuthorize注解,如果需要使用@securedEnabled注解,在加上 securedEnabled= true
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {}

   注解到@Controller方法上

@PreAuthorize("hasAuthority('course_pic_list')")
@PreAuthorize("hasAnyAuthority('p1','p2')")

ClientDetailsServiceConfigurer

//spring-security-oauth2需要配置redirectUris
//spring-cloud-starter-oauth2 不需要配置redirectUris

 clients.inMemory()
                .withClient("client-a") //client端唯一标识
                .secret(passwordEncoder.encode("client-a")) //客户端的密码,这里的密码应该是加密后的
                .authorizedGrantTypes("authorization_code") //授权模式标识
                .scopes("read_user_info") //作用域
                .resourceIds("resource1")//资源id
                .redirectUris("http://localhost:8080/callback"); //回调地址
        // @formatter: on

  

原文地址:https://www.cnblogs.com/yanxiaoge/p/14213753.html