四种模式测试
所有授权端点(EndterPoints),意思就是授权微服务启动后 可以访问哪些路径
认证服务器的ip以及端口号 localhost:8500
localhost:8500/oauth/token
路径 | 说明 |
/oauth/authoriz | 授权端点 |
/oauth/token | 令牌端点 获取token |
/oauth/confirm_access | 用户确认授权提交端点 |
/oauth/error | 授权服务错误信息端点 |
/oauth/check_token | 用于资源服务访问的令牌解析端点 |
/oauth/token_key | 提供公有密匙的端点,如果你使用JWT(RSA)令牌的 |
加依赖
<!-- oauth2-->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
授权码模式
1.访问授权站点,生成一个授权码
http://localhost:8081/oauth/authorize?response_type=code&client_id=admin&scop=all
授权码:osSyIp
2.授权码生成token
浏览器访问没有权限
生成的参数信息
简单模式
localhost:8081/oauth/authorize?response_type=token&client_id=admin&scope=all
客服端模式
localhost:8081/oauth/token?grant_type=client_credentials&client_id=admin&scope=all
密码模式
不支持这种类型
加入这个Bean
配置凭证信息
不想输入用户名和密码
对token放行
这样就实现了不需要密码和用户名
校验token
校验token的路径
localhost:8081/oauth/check_token?token=72c049e2-9f73-4da9-8146-25db9b2f2e91
JWT类型
加jwt依赖
<!--security使用的jwt-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
配置Bean
package com.aaa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import javax.annotation.Resource;
@Configuration
@EnableAuthorizationServer//认证配置
public class Myoauth2 extends AuthorizationServerConfigurerAdapter {
/**
* 客户端 第三方信息
* 用户
* 认证服务器
* 资源服务器
* @param clients
* @throws Exception
*/
@Resource
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Resource
private AuthenticationManager authenticationManager;
//* authorization_code 授权码模式
//* password 密码模式
//* implicit 简单模式
//* client_credentials 客户端模式
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("admin")//第三方客户端用户名
.secret(bCryptPasswordEncoder.encode("123456"))
.scopes("all")//全部
.authorities("all")//权限
.autoApprove(true)//自动授权
// .authorizedGrantTypes("authorization_code")//授权码模式
// .authorizedGrantTypes("implicit")//简单模式
// .authorizedGrantTypes("client_credentials")//客户端模式
.authorizedGrantTypes("password")
.redirectUris("https://www.baidu.com");
}
/**
* 配置凭证信息
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())//token存储的地方
.accessTokenConverter(jwtAccessTokenConverter());//生成token的Bean 解析token的Bean
}
/**
* 安全配置
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.checkTokenAccess("permitAll()")//检验token 放行
.tokenKeyAccess("permitAll()");//获取token的值
}
@Bean
public TokenStore tokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 生成token的Bean
* 解析token的Bean
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("cjh");
return jwtAccessTokenConverter;
}
}
使用Bean
认证之后直接生成token
安全配置文件中配置认证成功之后使用第三方工具 hutool 发出post请求 生成token 返回客户端
package com.aaa.config;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWTUtil;
import com.aaa.util.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().permitAll().loginProcessingUrl("/userlogin")
.successHandler((httpServletRequest, httpServletResponse, authentication) -> {
String username = httpServletRequest.getParameter("username");
String password = httpServletRequest.getParameter("password");
// hutool工具 发出一个post请求 获取token的值
HttpRequest post = HttpUtil.createPost("localhost:8081/oauth/token");
// 设置参数
post.form("grant_type","password");
post.form("client_id","admin");
post.form("client_secret","123456");
post.form("username",username);
post.form("password",password);
HttpResponse execute = post.execute();
String body = execute.body();
System.out.println(body);
// token的值
// 字符串转换为map
JSONObject entries = JSONUtil.parseObj(body);
Object accessToken = entries.get("access_token");
// 返回一个token
printJsonData(httpServletResponse,new Result(200,"成功",accessToken));
});
http.authorizeRequests().antMatchers("/userlogin","/oauth/**").permitAll();//放行这三个路径
http.authorizeRequests().anyRequest().authenticated();
// csrf 方便html 文件 都能通过
http.csrf().disable();
// 定义可以跨域
http.cors();
}
@Resource
private BCryptPasswordEncoder bCryptPasswordEncoder;
/**
* 配置密码模式的时候需要这个Bean
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager getAuthManager() throws Exception {
return super.authenticationManagerBean();
}
//安全框架的信息
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("cjh")
.password(bCryptPasswordEncoder.encode("123456"))
.roles("ADMIN");
// auth.userDetailsService(userDetailsService).passwordEncoder(getPassword());
}
// 封装一个方法
public void printJsonData(HttpServletResponse response, Result result){
try {
response.setContentType("application/json;charset=utf8");
// 使用objectMapper将 ResponseVo转换为json
ObjectMapper objectMapper=new ObjectMapper();
String s = objectMapper.writeValueAsString(result);
PrintWriter writer = response.getWriter();
writer.print(s);
writer.flush();
writer.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
资源服务器
加依赖
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
资源服务器配置文件
package com.aaa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(jsr250Enabled = true,prePostEnabled = true,securedEnabled = true)
public class MyResConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
//.access("@RbacConfig.hasPermission(request,authentication)")
.and()
.csrf().disable();
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("cjh");//认证服务器签名保持一致
return jwtAccessTokenConverter;
}
}
测试
请求时要把bearer加上
token验证成功