微服务授权 springsecurity+auth2基本入门

微服务登录问题:
解决方式:
我们使用客户端Token+oauth2+jwt+springsecurity
oauth2:简易,开放,安全,不接触账号密码
oauth2四种模式:

  • 授权码模式
  • 简化模式:没有授权码,直接token,安全性降低
  • 密码模式:一般在自己系统中用(不接触三方)
  • 客户端模式:不要用户名密码,直接返回token,在自己的服务器中使用,比如认证服务访问资源模式,你来访问我就直接返回token
  • 实现
  • 建立几个微服务
  • 1导包
  • 2搭建eureka,配置yml 注册eureka
  • 3搭建zuul 配置zuul
  • 4搭建resource 注册到eureka,开启zuul
  • 5搭建auth,注册到eureka,开启zuul
  • 6集成auth2
  • 导包
  • 7auth集成mybatis
  • 导入数据库到hrm-auth
  • 自定义UserDetailService
  • 根据name查询用户 基本判断用户
  • 查询所拥有的权限
  • 把用户和权限封装成一个UserDetailService
  • 把用户转成user 传参 用户名 密码 权限
  • 权限装成他所需要的集合
  • 返回一个UserDetailService

@Component
public class MyUserDetailService implements UserDetailsService {
    @Autowired
    private MyUserMapper myUserMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //通过username查询
        MyUser myUser = myUserMapper.loadByUsername(username);
        if(myUser==null){
            System.out.println(username + "用户不存在");
        }
        //通过用户查询所拥有的权限
        List<Permission> permissions = permissionMapper.loadByMyUserId(myUser.getId());
        List<SimpleGrantedAuthority> authorities=new ArrayList<>();
        permissions.forEach(permission -> {
            authorities.add(new SimpleGrantedAuthority(permission.getExpression()));
        });
        //转成需要的数组
        //参数需要 String username, String password, Collection<? extends GrantedAuthority> authorities
        User user=new User(myUser.getUsername(),myUser.getPassword(),authorities);
        return user;
    }
}

  • 配置springsecurity
  • 1继承websecurityConfigureAdapter
  • 2配置
  • 3开启springsecurity
  • 4密码匹配器
  • 5重写configure方法
/**
 * 对security安全配置
 */
@Configuration//相当于在xml 里面配置了bean
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter  {
    @Bean  //密码模式用到
   public AuthenticationManager authenticationManager() throws Exception {
      return    super.authenticationManager();
    }
    //配置认证管理器,授权模式为“poassword”时会用到
    //配置服务详情
    @Bean
    public ClientDetailsService clientDetailsService(){
        return new InMemoryClientDetailsService();
    }
    //配置一个编码器
    @Bean
    public PasswordEncoder passwordEncoder(){
      return   new BCryptPasswordEncoder();
    }
    //配置规则
    @Override
    public void configure(HttpSecurity http ) throws Exception {
        http.csrf().disable()//屏蔽跨域处理
                .authorizeRequests()//对请求做处理
                .antMatchers("/login").permitAll()//对登录放行
                .anyRequest().authenticated()//其他页面都要拦截
                .and().formLogin()//允许进行表单登录
                .successForwardUrl("/loginSuccess")//登录成功跳转
                .and().logout().permitAll();//登出放行
    }

}
  • 配置auth2 认证服务配置
  • 授权服务配置
  • 集成AuthorizationServer。。。
  • 开启服务授权配置
  • 复写三个方法
  • 一:基于内存客户端详情配置:创建了一个客户端详情类
  • 1配置客户端id
  • 2客户端密钥(注入密码匹配器给密钥加密)
  • 3资源id (颁发的令牌只能通过资源id访问对应的资源)
  • 4授权模式 客户端支持的授权模式
  • 5允许的授权范围
  • 6autoApprove(false)//是否自动授权
  • 7回调url
  • 二、授权服务端点配置(授权码和令牌管理)
  • 在security配置中配置认证管理器(父类返回一个认证管理器)
  • 1配置认证管理器
  • 先配置令牌服务bean
  • .配置令牌服务
  • 创建默认的令牌服务
  • 指定客户端详情配置
  • 2令牌服务配置
  • 配置一个bean基于内存的授权码配置
  • 3授权码配置
  • 4允许使用post发送请求
  • 三:授权服务安全配置
  • 放行检查token
  • 允许使用表单提交代码
  • 测试 然后测试密码模式
package cn.itsource.wyj.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

@Configuration
@EnableAuthorizationServer
public class ClientDetailsServiceConfig extends AuthorizationServerConfigurerAdapter {
    //一、配置客户端的参数
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //添加客户信息
        clients.inMemory()  //http://localhost:4000/oauth/authorize?client_id=www&response_type=code&redirect_uri=http://www.baidu.com
                .withClient("www")//添加客户端id
                .secret(passwordEncoder.encode("wyj"))//添加客户端密钥  加密
                .resourceIds("itsource")//添加资源id
                .authorizedGrantTypes("client_credentials",
                        "password","authorization_code","refresh_token")//允许授权类型
                .scopes("emp")//允许授权类型 为emp
                .autoApprove(false)//否需要跳转到授权页面让用户确认如果为true回直接发令牌
                .redirectUris("http://www.baidu.com");
    }

    @Bean //建token存储在内存中
    public TokenStore tokenStore(){
        return new InMemoryTokenStore();
    }

    //配置令牌
    @Autowired
    private ClientDetailsService clientDetailsService;
    public AuthorizationServerTokenServices tokenService(){
        //设置默认的令牌服务
        DefaultTokenServices defaultTokenServices=new DefaultTokenServices();
        //指定客户端详情配置
        defaultTokenServices.setClientDetailsService(clientDetailsService);
        //支持刷新token
        defaultTokenServices.setSupportRefreshToken(true);
        //token存储方式
        defaultTokenServices.setTokenStore(tokenStore());
        //token有效时间
        defaultTokenServices.setAccessTokenValiditySeconds(43200);//秒为单位
        //刷新默认有效时间
        defaultTokenServices.setRefreshTokenValiditySeconds(14400);
        return defaultTokenServices;
    }
    //配置令牌访问端点
    @Autowired
    private AuthenticationManager authenticationManager;
    @Bean//授权服务的bean
    public AuthorizationCodeServices authorizationCodeServices(){
        //基于内存存储的授权码服务
        return new InMemoryAuthorizationCodeServices();
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(authenticationManager)//配置认证管理器
        .authorizationCodeServices(authorizationCodeServices())//授权服务
        .tokenServices(tokenService())//配置令牌管理服务
        .allowedTokenEndpointRequestMethods(HttpMethod.POST);//允许post请求
        super.configure(endpoints);
    }
    //授权服务安全配置
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permiAll()")//放行检查token
                .checkTokenAccess("permiAll")//放行token检查
                .allowFormAuthenticationForClients();//允许客户端进行表单身份验证,使用表单认证申请令牌

    }
}

  • 四:配置资源
  • 1导包
  • 2建类继承Res。。
  • 开启资源服务配置
    -3 配置资源id
  • 4复写2个方法 //
  • 方法一:资源服务配置
  • 5配置bena-》token远程验证效验配置
  • 验证token
  • 5方法二:web安全配置
  • 判断授权范围
    使用方法授权现在se配置开启全局方法授权
  • 资源服务器检查token,通过认证管理器区检查token,调用userDetailservice,查询数据库的权限列表
//资源服务配置
@Configuration
@EnableResourceServer   //开启资源服务配置
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig implements ResourceServerConfigurer {
    //资源id
    private static final String RESOURCE_ID="res1";
    //资源服务安全性性配置
    @Bean
    public ResourceServerTokenServices resourceServerTokenServices(){
        //使用远程服务请求授权服务效验token
        RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
        //请求中必须携带token
        remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:4000/oauth/check_token");
        //客户端的id
        remoteTokenServices.setClientId("itsource");
        //密钥
        remoteTokenServices.setClientSecret("wyj");
        return remoteTokenServices;

    }
    @Override
    public void configure(ResourceServerSecurityConfigurer resourceServerSecurityConfigurer) throws Exception {
        resourceServerSecurityConfigurer.resourceId(RESOURCE_ID)//资源id
                .tokenServices(resourceServerTokenServices());//验证令牌
    }


    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .antMatchers("/**").access("#oauth2.hasScope('emp')")//校验scope必须为all , 对应认证服务的客户端详情配置的clientId
        .and().csrf().disable()//关闭跨越伪造检查
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//把session设置成无状态,使用了token不在用session做记录

    }
}

你可能感兴趣的:(SpringSecurity,spring,jwt)