博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springboot oauth 鉴权之——授权码authorization_code鉴权
阅读量:7010 次
发布时间:2019-06-28

本文共 9479 字,大约阅读时间需要 31 分钟。

 近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验。

第一步:什么是 OAuth鉴权

      是工业标准的授权协议。OAuth2取代了在2006创建的原始OAuthTM协议所做的工作。OAuth 2.0关注客户端开发人员的简单性,同时为Web应用程序、桌面应用程序、移动电话和客厅设备提供特定的授权流。

     参考理解:                  

第二步:什么是授权码模式

        授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

第三步:授权码授权流程

        

交互步骤:   (A)用户访问客户端,后者将前者导向认证服务器。   (B)用户选择是否给予客户端授权。  (C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。  (D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。  (E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

第四步:授权码模式实践

       源码地址:

               github: https://github.com/GitHubZhangCom/spring-security-oauth-example/

               码云:https://gitee.com/region/spring-security-oauth-example/

 1)、  引入相关jar: 

org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.0.0.RELEASE
org.projectlombok
lombok

 2)、相关oauth编程: 

 

package com.auth.server.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;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.userdetails.UserDetailsService;/** * 鉴权配置 * @author zyl * */@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Bean    @Override    public AuthenticationManager authenticationManagerBean() throws Exception {        return super.authenticationManagerBean();    }    @Qualifier("myUserDetailsService")    @Autowired    private UserDetailsService userDetailsService;    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.userDetailsService(userDetailsService);    }    @Override    protected void configure(HttpSecurity http) throws Exception {        http.authorizeRequests()                .antMatchers("/**/*.js",                        "/**/*.css"                )                .permitAll()                .anyRequest()                .authenticated()                .and()                .formLogin()                .loginPage("/login")                .permitAll()                // 自动登录                /*.and()                    .rememberMe()                    // 加密的秘钥                    .key("unique-and-secret")                    // 存放在浏览器端cookie的key                    .rememberMeCookieName("remember-me-cookie-name")                    // token失效的时间,单位为秒                    .tokenValiditySeconds(60 * 60 * 25)*/                .and()                // 暂时禁用CSRF,否则无法提交登录表单                .csrf().disable();    }}
package com.auth.server.config;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.core.userdetails.UserDetailsService;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.InMemoryTokenStore;/** * 授权配置 * @author wb0024 * */@Configuration@EnableAuthorizationServerpublic class ServerConfig extends AuthorizationServerConfigurerAdapter {    @Autowired    private AuthenticationManager authenticationManager;    @Qualifier("myUserDetailsService")    @Autowired    private UserDetailsService userDetailsService;//    @Autowired//    @Qualifier("dataSource")//    private DataSource dataSource;    @Override    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {        // 配置token获取和验证时的策略        security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");    }    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.inMemory()                .withClient("client")                // secret密码配置从 Spring Security 5.0开始必须以 {加密方式}+加密后的密码 这种格式填写                                /* *   当前版本5新增支持加密方式:                 *   bcrypt - BCryptPasswordEncoder (Also used for encoding)                 *   ldap - LdapShaPasswordEncoder                 *   MD4 - Md4PasswordEncoder                 *   MD5 - new MessageDigestPasswordEncoder("MD5")                 *   noop - NoOpPasswordEncoder                 *   pbkdf2 - Pbkdf2PasswordEncoder                 *   scrypt - SCryptPasswordEncoder                 *   SHA-1 - new MessageDigestPasswordEncoder("SHA-1")                 *   SHA-256 - new MessageDigestPasswordEncoder("SHA-256")                 *   sha256 - StandardPasswordEncoder*/                                 .secret("{noop}secret")                .scopes("all")                .authorizedGrantTypes("authorization_code")//授权码模式//                .authorizedGrantTypes("authorization_code", "refresh_token")//授权码模式                .autoApprove(true);    }    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//        // 配置tokenStore,保存到redis缓存中//        endpoints.authenticationManager(authenticationManager)//                .tokenStore(new MyRedisTokenStore(redisConnectionFactory))//                // 不添加userDetailsService,刷新access_token时会报错//                .userDetailsService(userDetailsService);        // 使用最基本的InMemoryTokenStore生成token        endpoints.authenticationManager(authenticationManager).tokenStore(memoryTokenStore());    }    // 使用最基本的InMemoryTokenStore生成token    @Bean    public TokenStore memoryTokenStore() {        return new InMemoryTokenStore();    }}

 

 

package com.jwt.server.provider;import java.util.ArrayList;import org.springframework.security.authentication.AuthenticationProvider;import org.springframework.security.authentication.BadCredentialsException;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;/** * 自定义身份认证验证组件 * @author zyl * */public class CustomAuthenticationProvider implements AuthenticationProvider {    private UserDetailsService userDetailsService;    private BCryptPasswordEncoder bCryptPasswordEncoder;    public CustomAuthenticationProvider(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder){        this.userDetailsService = userDetailsService;        this.bCryptPasswordEncoder = bCryptPasswordEncoder;    }    @Override    public Authentication authenticate(Authentication authentication) throws AuthenticationException {        // 获取认证的用户名 & 密码        String name = authentication.getName();        String password = authentication.getCredentials().toString();        // 认证逻辑        UserDetails userDetails = userDetailsService.loadUserByUsername(name);        if (null != userDetails) {            if (bCryptPasswordEncoder.matches(password, userDetails.getPassword())) {                // 这里设置权限和角色                ArrayList
authorities = new ArrayList<>(); authorities.add( new GrantedAuthorityImpl("ROLE_ADMIN")); authorities.add( new GrantedAuthorityImpl("ROLE_API")); authorities.add( new GrantedAuthorityImpl("AUTH_WRITE")); // 生成令牌 这里令牌里面存入了:name,password,authorities, 当然你也可以放其他内容 Authentication auth = new UsernamePasswordAuthenticationToken(name, password, authorities); return auth; } else { throw new BadCredentialsException("密码错误"); } } else { throw new UsernameNotFoundException("用户不存在"); } } /** * 是否可以提供输入类型的认证服务 * @param authentication * @return */ @Override public boolean supports(Class
authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); }}

 核心代码需要做的就这些,详情请看源码。

转载于:https://www.cnblogs.com/haoliyou/p/9606018.html

你可能感兴趣的文章
oracle编码转换:AL32UTF8->ZHS16GBK
查看>>
Unity Update 具体解释
查看>>
T-SQL动态查询(4)——动态SQL
查看>>
Ubuntu 16.04安装uGet替代迅雷,并在Chrome中设置为默认下载器
查看>>
MySQL缓存之Qcache与buffer pool对比
查看>>
springmvc(一) springmvc框架原理分析和简单入门程序
查看>>
别踩白块儿
查看>>
跟面试官讲Binder(零)
查看>>
mahout in Action2.2-聚类介绍-K-means聚类算法
查看>>
bootstrap-treeview 如何实现全选父节点下所有子节点及反选
查看>>
HTML5 CSS3 诱人的实例: 3D立方体旋转动画
查看>>
ElasticSearchserver操作命令
查看>>
ThreadPoolExecutor异常处理
查看>>
LeetCode 第 342 题(Power of Four)
查看>>
用QT搭建简单的播放器外壳
查看>>
索引设计指南
查看>>
Timus Online Judge 1057. Amount of Degrees(数位dp)
查看>>
jquery中关于表格行的增删问题
查看>>
分布式事务,EventBus 解决方案:CAP【中文文档】
查看>>
GUI进化--数据与界面分离
查看>>