學習Spring Security OAuth認證(一)-授權碼模式


一.環境

spring boot+spring security+idea+maven+mybatis

主要是spring security

二.依賴

    <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

不需要版本號,spring boot的pom中已經聲明了合適的版本號

三.springsecurity登錄配置

package com.haitian.security;

import com.haitian.service.security.CustomUserService;
import com.haitian.utils.PathUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.authentication.encoding.BasePasswordEncoder;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Locale;

/**
 * User:zhangweixiao
 * Description:
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private  UserDetailsService userDetailsService;

    @Bean
    public BasePasswordEncoder getPasswordEncoder()
    {
        return new Md5PasswordEncoder();
    }

   @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setPasswordEncoder(getPasswordEncoder());
        authProvider.setUserDetailsService(userDetailsService);
        return authProvider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ValidateCodeFilter validateCodeFilter=new ValidateCodeFilter();
        validateCodeFilter.setAuthenticationFailureHandler(authenticationFailureHandler);

        http
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .and()
                .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin().loginPage("/login").loginProcessingUrl("/zshop_login")
                .failureHandler(authenticationFailureHandler)
                .successHandler(authenticationSuccessHandler)
                .and()
                .csrf().disable();
    }

}

 

/**
 * 前台登錄的數據庫橋梁
 */
@Service
public class CustomUserService implements UserDetailsService{

    @Autowired
    private UserService userService;

    /**
     * @param username
     * @return
     * @throws UsernameNotFoundException
     * @throws DataAccessException
     */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {

        User user = this.userService.getUserByUserName(username);
        if (user == null) {
            throw new UsernameNotFoundException("用戶名不存在");
        }
        Set authorities = new HashSet();
        for (Role role : user.getRoles()) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleCode());
            authorities.add(grantedAuthority);
        }
        user.setAuthorities(authorities);
        return user;
    }

}

 

數據庫中User表對應的User類繼承了UserDetails,這里就不發了.

加密算法最好用bcrypt,因為數據庫存的是md5的,所以先用md5了.

了解加密:http://www.cnblogs.com/ptqueen/p/8448396.html

配置完成之后要保證能登錄成功.

四.配置認證服務器

 

1.配置注解提供認證服務器

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig {
}

2配置client-id和secret.

security:
  oauth2:
    client:
      client-id: zshop
      client-secret: zshop_secret

client-id就是第三方申請認證的id,前后端分離中前端也就相當於第三方.

你的認證服務器就好比QQ的認證服務器,你的前端就好比需要QQ第三方登錄的網站.

3啟動當前模塊

可以看到控制台中oath2包的為我們做的mapping

 Mapped "{[/oauth/authorize]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java. 
 
 Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)

4.用rest client插件測試

關於插件簡單介紹請看:

http://www.cnblogs.com/ptqueen/p/8449046.html

關於oath2文檔

https://tools.ietf.org/html/rfc6749#page-24

上面是oath2文檔中需要認證的參數信息

先這樣測試,http://localhost:8082/oauth/authorize?response_type=code&client_id=zshop&redirect_uri=https://cnblogs.com&scope=all

五.獲取授權碼code

關於授權碼模式的流程請看:

http://www.cnblogs.com/ptqueen/p/8449150.html

成功的話會跳轉到登錄頁面,這個登錄頁面相當於從某個論壇QQ登錄跳轉出來的登陸窗口

登錄成功后出現這樣一個

OAuth Approval

Do you authorize 'zshop' to access your protected resources?

  • scope.all:  Approve  Deny

 如果是自己的前端登錄成功之后應該會直接拿到所有權限,不顯示此頁面,然后繼續換取令牌,

第三方QQ登錄的 approval是和登錄頁面一起的.后面看看怎么配置.

同意授權之后會跳轉到https://cnblogs.com,同時會攜帶一個code,這個code就是授權碼.下一步需要通過授權碼來換取令牌.

https://www.cnblogs.com/?code=D120US

六.發送授權碼到認證服務器換取令牌

參照oauth2文檔

https://tools.ietf.org/html/rfc6749#page-29

post的參數有

grant_tpye,值必須為authorization_code

code,第一篇中獲得的授權碼

redirect_uri,必須和第一篇相同

client_id,配置文件中定義的client_id

scope,獲取授權碼時定義的scope

請求的header中需要包含client-id和client-secret.

 



七.獲得令牌

成功之后即可獲取,令牌是有有效期的,必須在有效期之前進行刷新

 

{
"access_token":  "f035137f-def1-4bae-9adc-718a26e6c141",
"token_type":  "bearer",
"refresh_token":  "e7f65ace-6c5d-44a6-94fb-e7ca65ff12fd",
"expires_in":  43199,
"scope":  "all"
}

 

lines nums

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM