Springboot Oauth2 Server搭建Oauth2认证服务的示例(oauth2,server,springboot,编程语言)

时间:2024-05-08 09:54:58 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

介绍

这里我将介绍两个部分

  • Oauth3 server 的开发 (hi-auth-web模块)

  • Oauth3 client 的开发 (hi-mall-web模块)

效果图

Springboot Oauth2 Server搭建Oauth2认证服务的示例

himall.gif

Springboot Oauth2 Server搭建Oauth2认证服务的示例

umc.gif

LIVE DEMO

HiMall: http://hiauth.cn/himall

UMC: http://hiauth.cn/umc

Swagger2:http://hiauth.cn/hiauth/swagger-ui.html

Oauth3 server 搭建

数据库表(mysql5.6),其中只有sys_user表由我们自己控制,其他表由框架控制

CREATETABLEclientdetails(
appIdvarchar(255)NOTNULL,
resourceIdsvarchar(256)DEFAULTNULL,
appSecretvarchar(256)DEFAULTNULL,
scopevarchar(256)DEFAULTNULL,
grantTypesvarchar(256)DEFAULTNULL,
redirectUrlvarchar(256)DEFAULTNULL,
authoritiesvarchar(256)DEFAULTNULL,
access_token_validityint(11)DEFAULTNULL,
refresh_token_validityint(11)DEFAULTNULL,
additionalInformationvarchar(4096)DEFAULTNULL,
autoApproveScopesvarchar(256)DEFAULTNULL,
PRIMARYKEY(appId)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEoauth_access_token(
token_idvarchar(256)DEFAULTNULL,
tokenblob,
authentication_idvarchar(255)NOTNULL,
user_namevarchar(256)DEFAULTNULL,
client_idvarchar(256)DEFAULTNULL,
authenticationblob,
refresh_tokenvarchar(256)DEFAULTNULL,
PRIMARYKEY(authentication_id)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEoauth_approvals(
userIdvarchar(256)DEFAULTNULL,
clientIdvarchar(256)DEFAULTNULL,
scopevarchar(256)DEFAULTNULL,
statusvarchar(10)DEFAULTNULL,
expiresAttimestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,
lastModifiedAttimestampNOTNULLDEFAULT'0000-00-0000:00:00'
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEoauth_client_details(
client_idvarchar(255)NOTNULL,
resource_idsvarchar(256)DEFAULTNULL,
client_secretvarchar(256)DEFAULTNULL,
scopevarchar(256)DEFAULTNULL,
authorized_grant_typesvarchar(256)DEFAULTNULL,
web_server_redirect_urivarchar(2560)DEFAULTNULL,
authoritiesvarchar(256)DEFAULTNULL,
access_token_validityint(11)DEFAULTNULL,
refresh_token_validityint(11)DEFAULTNULL,
additional_informationvarchar(4096)DEFAULTNULL,
autoapprovevarchar(256)DEFAULTNULL,
PRIMARYKEY(client_id)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

INSERTINTOoauth_client_detailsVALUES('client',null,'$2a$10$1N/.LvTJuYpvxDzoJ1KdvuPDdV/kDSQE9Cxm9BzB1PreyzK6gmFRe','ALL,AUTH,USER,GOODS,ORDER','authorization_code,client_credentials,password,refresh_token','http://localhost:8081/mall/callback,http://localhost:9080/user/webjars/springfox-swagger-ui/oauth3-redirect.html,http://localhost:9081/goods/webjars/springfox-swagger-ui/oauth3-redirect.html,http://localhost:9082/order/webjars/springfox-swagger-ui/oauth3-redirect.html,http://localhost/user/webjars/springfox-swagger-ui/oauth3-redirect.html,http://localhost/goods/webjars/springfox-swagger-ui/oauth3-redirect.html,http://localhost/order/webjars/springfox-swagger-ui/oauth3-redirect.html','ROLE_USER','1800','86400',null,'false');

CREATETABLEoauth_client_token(
token_idvarchar(256)DEFAULTNULL,
tokenblob,
authentication_idvarchar(255)NOTNULL,
user_namevarchar(256)DEFAULTNULL,
client_idvarchar(256)DEFAULTNULL,
PRIMARYKEY(authentication_id)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEoauth_code(
codevarchar(256)DEFAULTNULL,
authenticationblob
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEoauth_refresh_token(
token_idvarchar(256)DEFAULTNULL,
tokenblob,
authenticationblob
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

CREATETABLEsys_user(
idbigint(20)NOTNULL,
namevarchar(20)DEFAULTNULL,
usernamevarchar(20)NOTNULL,
passwordvarchar(128)NOTNULL,
telvarchar(20)DEFAULTNULL,
gendervarchar(10)DEFAULTNULL,
createTimedatetimeDEFAULTNULL,
PRIMARYKEY(id),
UNIQUEKEYunique_username(username),
UNIQUEKEYunique_tel(tel)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;

INSERTINTOsys_userVALUES('1','张三','admin','123456','13712345678','MALE','2018-12-0317:57:12');
INSERTINTOsys_userVALUES('2','李四','user','123456','13812345678','UNKNOWN','2018-12-0317:57:12');

pom.xml如下

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth3</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>

添加表sys_user的service、mapper

@Mapper
publicinterfaceUserMapper{

@Insert("INSERTINTOsys_user(id,name,username,password,tel,gender,createTime)VALUES(#{id},#{name},#{username},#{password},#{tel},#{gender},#{createTime})")
voidinsert(Useruser);

@Delete("DELETEFROMsys_userWHEREid=#{id}")
voiddelete(Longid);

@Update("UPDATEsys_userSETname=#{name},username=#{username},password=#{password},tel=#{tel},gender=#{gender},createTime=#{createTime}WHEREid=#{id}")
intupdate(Useruser);

@ResultMap("BaseResultMap")
@Select("SELECT*FROMsys_userWHEREid=#{id}")
UserfindById(Longid);

@ResultMap("BaseResultMap")
@Select("SELECT*FROMsys_userWHEREusername=#{username}")
UserfindByUsername(Stringusername);

@ResultMap("BaseResultMap")
@Select("SELECT*FROMsys_userWHEREtel=#{tel}")
UserfindByTel(Stringtel);

@ResultMap("BaseResultMap")
@Select("SELECT*FROMsys_user")
List<User>findAll();

@ResultMap("BaseResultMap")
@Select("SELECT*FROMsys_userWHEREnamelike#{name}")
List<User>findByName(Stringname);

}

@Service
publicclassUserServiceImplimplementsUserService{

@Resource
UserMappermapper;

@Override
publicUsersave(Useruser){
if(user.getId()!=null){
mapper.update(user);
}else{
user.setId(System.currentTimeMillis());
mapper.insert(user);
}
returnuser;
}

@Override
publicUserfindById(Longid){
returnmapper.findById(id);
}

@Override
publicUserfindByUsername(Stringusername){
returnmapper.findByUsername(username);
}

@Override
publicUserfindByTel(Stringtel){
returnmapper.findByTel(tel);
}

@Override
publicList<User>findAll(){
returnmapper.findAll();
}

@Override
publicvoiddelete(Longid){
mapper.delete(id);
}

@Override
publicList<User>findByName(Stringname){
returnmapper.findByName("%"+name+"%");
}

}

添加登录拦截

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{

@Bean
publicPasswordEncoderpasswordEncoder(){
returnnewBCryptPasswordEncoder();
}

@Bean
publicUserDetailsServicesimpleUserDetailsService(){
returnnewUserDetailsServiceImpl();
}

@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.userDetailsService(simpleUserDetailsService());
}

@Override
@Bean
publicAuthenticationManagerauthenticationManagerBean()throwsException{
returnsuper.authenticationManagerBean();
}

@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{

http.userDetailsService(userDetailsService());
http.csrf().disable();
http.formLogin()
.loginPage("/signin").loginProcessingUrl("/signin/form/account").defaultSuccessUrl("/index")
.and()
.logout().logoutUrl("/signout").logoutSuccessUrl("/signin")
.and()
.authorizeRequests()
.antMatchers("/signin","/signin/form/tel","/code/image","/code/mobile","/static/").permitAll()
.antMatchers("/oauth/
").permitAll()
.antMatchers("/user/**").hasAnyRole("USER","ADMIN")
.anyRequest().authenticated();

}

}

添加登录表单signin.html

<divclass="tab-panefadeinactive"id="account-login">
<formth:action="@{/signin/form/account}"method="post">
<labelfor="username"class="sr-only">用户名</label>
<inputclass="form-control"type="text"name="username"id="username"value="user"placeholder="账号"required>
<labelfor="password"class="sr-only">密码</label>
<inputclass="form-control"type="password"name="password"id="password"value="123456"placeholder="密码"required>
<buttonclass="btnbtn-lgbtn-primarybtn-block"type="submit">登录</button>
</form>
</div>

Oauth3 server Config

@Configuration
@EnableAuthorizationServer
publicclassOAuth3AuthorizationConfigextendsAuthorizationServerConfigurerAdapter{

@Autowired
privateEnvironmentenv;

@Autowired
privateAuthenticationManagerauthenticationManager;

/*
自定义授权页面
*/
@Autowired
privateAuthorizationEndpointauthorizationEndpoint;

@PostConstruct
publicvoidinit(){
authorizationEndpoint.setUserApprovalPage("forward:/oauth/my_approval_page");
authorizationEndpoint.setErrorPage("forward:/oauth/my_error_page");
}

@Bean
publicDataSourcedataSource(){
finalDriverManagerDataSourcedataSource=newDriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
returndataSource;
}

@Bean
publicApprovalStoreapprovalStore(){
returnnewJdbcApprovalStore(dataSource());
}

@Bean
protectedAuthorizationCodeServicesauthorizationCodeServices(){
returnnewJdbcAuthorizationCodeServices(dataSource());
}

@Bean
publicTokenStoretokenStore(){
returnnewJdbcTokenStore(dataSource());
}

@Override
publicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{
//oauth_client_details
clients.jdbc(dataSource());
}

@Override
publicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints){
//oauth_approvals
endpoints.approvalStore(approvalStore());
//oauth_code
endpoints.authorizationCodeServices(authorizationCodeServices());
//oauth_access_token&oauth_refresh_token
endpoints.tokenStore(tokenStore());
//支持passwordgranttype
endpoints.authenticationManager(authenticationManager);
}

@Override
publicvoidconfigure(AuthorizationServerSecurityConfigureroauthServer){
oauthServer.allowFormAuthenticationForClients();
}
}

Oauth3 client 搭建

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-apis</artifactId>
<version>5.0.0</version>
</dependency>

DefaultApi20

publicclassAiwanApiextendsDefaultApi20{

privateStringaccessTokenEndpoint="http://localhost:8080/oauth/token&quot;;
privateStringauthorizationBaseUrl="http://localhost:8080/oauth/authorize&quot;;

protectedAiwanApi(){}

privatestaticclassInstanceHolder{
privatestaticfinalAiwanApiINSTANCE=newAiwanApi();
}

publicstaticAiwanApiinstance(){
returnInstanceHolder.INSTANCE;
}

@Override
publicStringgetAccessTokenEndpoint(){
returnaccessTokenEndpoint;
}

@Override
protectedStringgetAuthorizationBaseUrl(){
returnauthorizationBaseUrl;
}

@Override
publicTokenExtractor<OAuth3AccessToken>getAccessTokenExtractor(){
returnOAuth3AccessTokenJsonExtractor.instance();
}

@Override
publicOAuth30ServicecreateService(OAuthConfigconfig){
returnnewAiwanService(this,config);
}

}

OAuth30Service

publicclassAiwanServiceextendsOAuth30Service{

publicAiwanService(DefaultApi20api,OAuthConfigconfig){
super(api,config);
}

@Override
protectedOAuthRequestcreateAccessTokenRequest(Stringcode){
finalOAuthRequestrequest=newOAuthRequest(getApi().getAccessTokenVerb(),getApi().getAccessTokenEndpoint());
finalOAuthConfigconfig=getConfig();
request.addParameter(OAuthConstants.CLIENT_ID,config.getApiKey());
finalStringapiSecret=config.getApiSecret();
if(apiSecret!=null){
request.addParameter(OAuthConstants.CLIENT_SECRET,apiSecret);
}
request.addParameter(OAuthConstants.CODE,code);
request.addParameter(OAuthConstants.REDIRECT_URI,config.getCallback());
finalStringscope=config.getScope();
if(scope!=null){
request.addParameter(OAuthConstants.SCOPE,scope);
}
request.addParameter(OAuthConstants.GRANT_TYPE,OAuthConstants.AUTHORIZATION_CODE);
request.addHeader(OAuthConstants.HEADER,
OAuthConstants.BASIC+''
+Base64Encoder.getInstance()
.encode(String.format("%s:%s",config.getApiKey(),apiSecret).getBytes(Charset.forName("UTF-8"))));
returnrequest;
}
}

获取access_token

@Controller
publicclassIndexController{

privatestaticLoggerlogger=LoggerFactory.getLogger(IndexController.class);

privatestaticfinalStringSESSION_KEY_ACCESS_TOKEN="MY_ACCESS_TOKEN";

/*
为防止CSRF跨站攻击,每次请求STATE的值应该不同,可以放入Session!
由于都是localhost测试,所以session无法保持,用一个固定值。
/
privatestaticfinalStringSTATE="secret-rensanning";
privatestaticfinalStringCLIENT_ID="client";
privatestaticfinalStringCLIENT_SECRET="123456";
privatestaticfinalStringCALLBACK_URL="http://localhost:8081/mall/callback&quot;;
privatestaticfinalStringSCOPE="ALL";
privateOAuth30ServiceaiwanApi=newServiceBuilder(CLIENT_ID)
.apiSecret(CLIENT_SECRET)
.scope(SCOPE)
.state(STATE)
.callback(CALLBACK_URL)
.build(AiwanApi.instance());

@GetMapping("/")
publicStringindex(){
return"index";
}

@GetMapping("/signin")
publicvoidsignin(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{
logger.debug("signin");
logger.info("sessionid:{}",request.getSession().getId());
StringauthorizationUrl=aiwanApi.getAuthorizationUrl();
logger.info("redirectURL:{}",authorizationUrl);
response.sendRedirect(authorizationUrl);
}

@GetMapping("/callback")
publicStringcallback(@RequestParam(value="code",required=false)Stringcode,
@RequestParam(value="state",required=false)Stringstate,HttpServletRequestrequest)throwsException{

logger.debug("callback[code:{}],[state:{}],[sessionId:{}]",code,state,request.getSession().getId());

if(STATE.equals(state)){
logger.info("StateOK!");
}else{
logger.error("StateNG!");
}

OAuth3AccessTokenaccessToken=aiwanApi.getAccessToken(code);
request.getSession().setAttribute(SESSION_KEY_ACCESS_TOKEN,accessToken);

return"profile";
}

}

相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

本文:Springboot Oauth2 Server搭建Oauth2认证服务的示例的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:SpringBoot如何实现动态控制定时任务支持多参数功能下一篇:

16 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18