热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

中心服务器授权许可文件,springcloudoauth2搭建认证中心(授权服务器)

单点登录什么是单点登录?单点登录全称SingleSignOn(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到

单点登录

什么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分

相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理。

oauth2

在oauth中我们通常将他分为认证中心和资源中心。二者可以放在一起,但是对于微服务来说,每个独自的微服务可能就是一个资源中心。

在oauth2中有几种授权模式:

1、授权码模式

2、密码模式

3、客户端模式

4、简易模式

具体请求流程不是本文中点,我们着重讲解Spring cloud oauth2搭建认证中心。

在oauth中我们通常将他分为认证中心和资源中心。

对于我们的微服务来说,每个独立的微服务即是一个个资源中心,用户想要请求微服务的数据,需要携带认证中心颁发的tocken。

1.引入相关pom依赖

这里我们使用1.5.2.RELEASE的spring boot版本,因为我们会将oauth2交给cloud管理,所以我们同时引入了cloud的依赖,cloud版本使用SR5

org.springframework.boot

spring-boot-starter-parent

1.5.2.RELEASE

org.springframework.cloud

spring-cloud-dependencies

Finchley.SR5

pom

import

org.springframework.cloud

spring-cloud-starter-eureka-server

org.springframework.boot

spring-boot-starter-test

test

net.logstash.logback

logstash-logback-encoder

org.springframework.cloud

spring-cloud-starter-security

true

org.springframework.cloud

spring-cloud-starter-oauth2

org.springframework.security.oauth

spring-security-oauth2

javax.inject

javax.inject

org.springframework.boot

spring-boot-starter-data-redis

mysql

mysql-connector-java

runtime

org.mybatis.spring.boot

mybatis-spring-boot-starter

com.alibaba

fastjson

2.编写spring boot启动类

@SpringBootApplication

@Configuration

@EnableTransactionManagement

@MapperScan(basePackages = {

"com.dahaonetwork.smartfactory.authserver.mapper"

})

public class AuthenticationApplication {

/** 主类 */

public static void main(String[] args) {

SpringApplication.run(AuthenticationApplication.class, args);

}

}

3.声明一个授权服务器

声明一个授权服务器只需要继承 AuthorizationServerConfigurerAdapter,添加

@EnableAuthorizationServer 注解。

@EnableAuthorizationServer 这个注解告诉 Spring 这个应用是 OAuth2 的认证中心。

并且复写如下三个方法:

ClientDetailsServiceConfigurer:这个configurer定义了客户端细节服务。客户详细信息可以被初始化。

AuthorizationServerSecurityConfigurer:在令牌端点上定义了安全约束。

AuthorizationServerEndpointsConfigurer:定义了授权和令牌端点和令牌服务。

配置客户端详细步骤

ClientDetailsServiceConfigurer 类(AuthorizationServerConfigurer类中的一个调用类)可以用来定义一个基于内存的或者JDBC的客户端信息服务。

客户端对象重要的属性有:

clientId:(必须)客户端id。

secret:(对于可信任的客户端是必须的)客户端的私密信息。

scope:客户端的作用域。如果scope未定义或者为空(默认值),则客户端作用域不受限制。

authorizedGrantTypes:授权给客户端使用的权限类型。默认值为空。

authorities:授权给客户端的权限(Spring普通的安全权限)。

在运行的应用中,可以通过直接访问隐藏的存储文件(如:JdbcClientDetailsService中用到的数据库表)或者通过实现ClientDetailsManager 接口(也可以实现ClientDetailsService 接口,或者实现两个接口)来更新客户端信息。

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception{...}

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {...}

@Override

public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {...}

具体代码如下所示:这里我们将tocken信息存储在mysql中,分布式下你可以存储在redis中,全局共享。

@Configuration

@EnableAuthorizationServer

public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{

@Autowired

@Qualifier("authenticationManagerBean")

private AuthenticationManager authenticationManager;

@Autowired

private RedisConnectionFactory connectionFactory;

@Autowired

private DataSource dataSource;

/**

* @Title: tokenStore

* @Description: 用户验证信息的保存策略,可以存储在内存中,关系型数据库中,redis中

* @param

* @return TokenStore

* @throws

*/

@Bean

public TokenStore tokenStore(){

//return new RedisTokenStore(connectionFactory);

//return new InMemoryTokenStore();

return new JdbcTokenStore(dataSource);

}

@Bean // 声明 ClientDetails实现

public ClientDetailsService clientDetails() {

return new JdbcClientDetailsService(dataSource);

}

/**

*

* 这个方法主要是用于校验注册的第三方客户端的信息,可以存储在数据库中,默认方式是存储在内存中,如下所示,注释掉的代码即为内存中存储的方式

*/

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception{

// clients.inMemory()

// .withClient("client").secret("123456").scopes("read")

// .authorizedGrantTypes("authorization_code", "password", "refresh_token")

// .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT");

// //.authorizedGrantTypes("password","authorization_code","client_credentials","refresh_token");

// //.authorizedGrantTypes("password","refresh_token");

// //.redirectUris("https://www.getpostman.com/oauth2/callback");

// /*redirectUris 关于这个配置项,是在 OAuth2协议中,认证成功后的回调地址,此值同样可以配置多个*/

clients.withClientDetails(clientDetails());

clients.jdbc(dataSource);

}

/**

* 这个方法主要的作用用于控制token的端点等信息

*/

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.authenticationManager(authenticationManager);

endpoints.tokenStore(tokenStore());

//endpoints.userDetailsService(userService);

// 配置TokenServices参数 可以考虑使用[DefaultTokenServices],它使用随机值创建令牌

DefaultTokenServices tokenServices = new DefaultTokenServices();

tokenServices.setTokenStore(endpoints.getTokenStore());

tokenServices.setSupportRefreshToken(true);

tokenServices.setClientDetailsService(endpoints.getClientDetailsService());

tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());

tokenServices.setAccessTokenValiditySeconds( (int) TimeUnit.DAYS.toSeconds(30)); // 30天

endpoints.tokenServices(tokenServices);

}

/**

允许表单验证,浏览器直接发送post请求即可获取tocken

*/

@Override

public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(

"isAuthenticated()");

oauthServer.allowFormAuthenticationForClients();

}

}

4开启Spring Security的功能

spring security用来验证用户账号密码,对请求路劲做处理等。继承WebSecurityConfigurerAdapter 使用@EnableWebMvcSecurity 注解开启Spring Security的功能。

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired

private MyAuthenticationProvider provider;

@Autowired

private UserDetailsService userService;

/**

* 用户认证

*/

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.authenticationProvider(provider);

auth.userDetailsService(userService);

// auth.inMemoryAuthentication()

// .withUser("user").password("123456").authorities("ROLE_USER");

}

/**

* 1:

* 请求授权:

* spring security 使用以下匹配器来匹配请求路劲:

* antMatchers:使用ant风格的路劲匹配

* regexMatchers:使用正则表达式匹配路劲

* anyRequest:匹配所有请求路劲

* 在匹配了请求路劲后,需要针对当前用户的信息对请求路劲进行安全处理。

* 2:定制登录行为。

* formLogin()方法定制登录操作

* loginPage()方法定制登录页面访问地址

* defaultSuccessUrl()登录成功后转向的页面

* permitAll()

*/

@Override

protected void configure(HttpSecurity http) throws Exception {

http

.authorizeRequests()

.antMatchers(

StaticParams.PATHREGX.API,

StaticParams.PATHREGX.CSS,

StaticParams.PATHREGX.JS,

StaticParams.PATHREGX.IMG).permitAll()//允许用户任意访问

.anyRequest().authenticated()//其余所有请求都需要认证后才可访问

.and()

.formLogin()

//.loginPage("/login/login.do") /

//.defaultSuccessUrl("/hello2")

.permitAll();//允许用户任意访问

http.csrf().disable();

}

/**

* 密码模式下必须注入的bean authenticationManagerBean

* 认证是由 AuthenticationManager 来管理的,

* 但是真正进行认证的是 AuthenticationManager 中定义的AuthenticationProvider。

* AuthenticationManager 中可以定义有多个 AuthenticationProvider

*/

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

}

5自定义用户认证实现

认证是由AuthenticationManager 来管理的,

但是真正进行认证的是 AuthenticationManager 中定义的AuthenticationProvider。

AuthenticationManager 中可以定义有多个 AuthenticationProvider,

我们在四步骤中AuthenticationManagerBuilder中添加了当前的Provider 。

@Named

@Component

public class MyAuthenticationProvider extends DaoAuthenticationProvider {

/** 规则校验 */

@Resource(name = "passwordService")

private PasswordService passwordService;

protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

// 构造函数中注入

@Inject

public MyAuthenticationProvider(UserDetailsService userDetailsService)

{

this.setUserDetailsService(userDetailsService);

}

/**

* 自定义验证方式

*/

@Override

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

String username = authentication.getName();

String password = (String) authentication.getCredentials();

MyUserDetails userDetails = (MyUserDetails)

this.getUserDetailsService().loadUserByUsername(username);

//按登录规则校验用户

passwordService.validateRules(userDetails.getUser(), password);

Collection extends GrantedAuthority> authorities = userDetails.getAuthorities();

Authentication authenticationToken = new UsernamePasswordAuthenticationToken(JSON.toJSONString(userDetails,SerializerFeature.WriteMapNullValue), password, authorities);

return authenticationToken;

}

@Override

public boolean supports(Class> arg0) {

return true;

}

}

6自定义UserDetailsService

自定义需要实现UserDetailsService接口,并且重写loadUserByUsername方法。返回的用户信息需要实现UserDatails接口。

@Service("userInfo")

public class UserInfoService implements UserDetailsService{

@Autowired

private UserMapper userMapper;

@Override

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

// TODO Auto-generated method stub

Map paramMap=new HashMap();

paramMap.put("loginId", username);

User user=userMapper.getUserByloginIds(paramMap);

if(user ==null) {

throw new BadCredentialsException(Constants.getReturnStr(Constants.USER_NOT_FOUND, Constants.USER_NOT_FOUND_TIPS));

}

MyUserDetails userDetails = new MyUserDetails();

userDetails.setUserName(username);

userDetails.setPassword(user.getPassword());

userDetails.setUser(user);

return userDetails;

}

}

public class MyUserDetails implements UserDetails{

private static final long seriaVersionUID=1L;

private String userName;

private String password;

private User user;

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public void setPassword(String password) {

this.password = password;

}

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

/**

* 重写getAuthorities方法,将用户的角色作为权限

*/

@Override

public Collection extends GrantedAuthority> getAuthorities() {

//TODO 后续带完善

return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_SUPER");

}

@Override

public String getPassword() {

return password;

}

@Override

public String getUsername() {

return userName;

}

@Override

public boolean isAccountNonExpired() {

return true;

}

@Override

public boolean isAccountNonLocked() {

return true;

}

@Override

public boolean isCredentialsNonExpired() {

return true;

}

@Override

public boolean isEnabled() {

return true;

}

}

7相关数据库表结构

8相关配置文件

spring.application.name=oauth-server

server.port=8043

server.context-path=/uaa

logging.level.org.springframework.security=DEBUG

security.oauth2.resource.serviceId= ${PREFIX:}resource

security.oauth2.resource.filter-order=3

database.url=jdbc:mysql://192.168.7.175:3306/oauth2

spring.datasource.url=${database.url}?useUnicode\=true&characterEncoding\=UTF-8&useOldAliasMetadataBehavior\=true

spring.datasource.username=devdb

spring.datasource.password=

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

logging.level.root=info

logging.level.com.dahaonetwork.smartfactory.authserver=debug

logging.level.org.springframework.security=info

#mybatis show sql

logging.level.org.springframework=WARN

spring.thymeleaf.cache=false

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true

mybatis.mapper-locations=classpath:mapper/*.xml

9测试

这里我们使用密码模式来获取tocken:

d3901772c95a

这样认证服务器就搭建完成了,浏览器只需要携带tocken就可以访问资源服务器上的相关信息。



推荐阅读
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • Linux下部署Symfoy2对app/cache和app/logs目录的权限设置,symfoy2logs
    php教程|php手册xml文件php教程-php手册Linux下部署Symfoy2对appcache和applogs目录的权限设置,symfoy2logs黑色记事本源码,vsco ... [详细]
  • Oracle 和 mysql的9点区别【MySQL】
    数据库|mysql教程oracle,Oracle,money,mysql,coun数据库-mysql教程1.组函数用法规则mysql中组函数在select语句中可以随意使用,但在o ... [详细]
  • 1.脚本功能1)自动替换jar包中的配置文件。2)自动备份老版本的Jar包3)自动判断是初次启动还是更新服务2.脚本准备进入ho ... [详细]
  • ORACLE空间管理实验5:块管理之ASSM下高水位的影响
    数据库|mysql教程ORACLE,空间,管理,实验,ASSM,下高,水位,影响,数据库-mysql教程易语言黑客软件源码,vscode左侧搜索,ubuntu怎么看上一页,ecs搭 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringCloudRibbon部分源码相关的知识,希望对你有一定的参考价值。1:ribbon是提供通过servi ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了如何清除Eclipse中SVN用户的设置。首先需要查看使用的SVN接口,然后根据接口类型找到相应的目录并删除相关文件。最后使用SVN更新或提交来应用更改。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
author-avatar
潇潇雨621715
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有