1. 程式人生 > >Spring boot+Security OAuth2 自定義登入和授權頁面

Spring boot+Security OAuth2 自定義登入和授權頁面

Spring boot+Security OAuth2 自定義登入和授權頁面

 

1. 依賴

<!---------thymeleaf 模板引擎-------->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  •  

thymeleaf 配置

spring:
	thymeleaf:
    	prefix: classpath:/views/
    	suffix: .html
    	cache: false
  •  

2. 前端頁面

自定義登入頁面肯定要有自己的頁面,先從頁面入手,在resources 目錄下新建views 目錄,在此目錄下新建base-login.html 檔案如下:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登入</title>
</head>

<style>
    .login-container {
        margin: 50px;
        width: 100%;
    }

    .form-container {
        margin: 0px auto;
        width: 50%;
        text-align: center;
        box-shadow: 1px 1px 10px #888888;
        height: 300px;
        padding: 5px;
    }

    input {
        margin-top: 10px;
        width: 350px;
        height: 30px;
        border-radius: 3px;
        border: 1px #E9686B solid;
        padding-left: 2px;

    }


    .btn {
        width: 350px;
        height: 35px;
        line-height: 35px;
        cursor: pointer;
        margin-top: 20px;
        border-radius: 3px;
        background-color: #E9686B;
        color: white;
        border: none;
        font-size: 15px;
    }

    .title{
        margin-top: 5px;
        font-size: 18px;
        color: #E9686B;
    }
</style>
<body>
<div class="login-container">
    <div class="form-container">
        <p class="title">使用者登入</p>
        <form name="loginForm" method="post" th:action="${loginProcessUrl}">
            <input type="text" name="username" placeholder="使用者名稱"/>
            <br>
            <input type="password" name="password" placeholder="密碼"/>
            <br>
            <button type="submit" class="btn">登 &nbsp;&nbsp; 錄</button>
        </form>
        <p style="color: red" th:if="${param.error}">使用者名稱或密碼錯誤</p>
    </div>
</div>
</body>
</html>
  •  

在views資料夾下新建base-grant.html 授權頁面檔案,如下所示

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>授權</title>
</head>
<style>

    html{
        padding: 0px;
        margin: 0px;
    }

    .title {
        background-color: #E9686B;
        height: 50px;
        padding-left: 20%;
        padding-right: 20%;
        color: white;
        line-height: 50px;
        font-size: 18px;
    }
    .title-left{
        float: right;
    }
    .title-right{
        float: left;
    }
    .title-left a{
        color: white;
    }
    .container{
        clear: both;
        text-align: center;
    }
    .btn {
        width: 350px;
        height: 35px;
        line-height: 35px;
        cursor: pointer;
        margin-top: 20px;
        border-radius: 3px;
        background-color: #E9686B;
        color: white;
        border: none;
        font-size: 15px;
    }
</style>
<body style="margin: 0px">
<div class="title">
    <div class="title-right">OAUTH-BOOT 授權</div>
    <div class="title-left">
        <a href="#help">幫助</a>
    </div>
</div>
    <div class="container">
         <h3 th:text="${clientId}+' 請求授權,該應用將獲取你的以下資訊'"></h3>
        <p>暱稱,頭像和性別</p>
         授權後表明你已同意 <a  href="#boot" style="color: #E9686B">OAUTH-BOOT 服務協議</a>
        <form method="post" action="/oauth/authorize">
            <input type="hidden" name="user_oauth_approval" value="true">
            <input type="hidden" name="_csrf" th:value="${_csrf.getToken()}"/>
            <button class="btn" type="submit"> 同意/授權</button>
        </form>
    </div>
</body>
</html>
  •  

3. Controller

登入頁面controller如下

@Controller
public class BaseMainController {
    @Autowired
    private BootSecurityProperties properties;

    @GetMapping("/auth/login")
    public String loginPage(Model model){
        model.addAttribute("loginProcessUrl",properties.getLoginProcessUrl());
        return "base-login";
    }
}
  •  

4. WebSecurity 配置

授權前的使用者認證有Security 提供,將自定義的登入頁面配置進去

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private BootUserDetailService userDetailService;

    @Autowired
    private BootSecurityProperties properties;

    /**
     * 讓Security 忽略這些url,不做攔截處理
     *
     * @param
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers
                ("/swagger-ui.html/**", "/webjars/**",
                        "/swagger-resources/**", "/v2/api-docs/**",
                        "/swagger-resources/configuration/ui/**", "/swagger-resources/configuration/security/**",
                        "/images/**");
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService);
    }

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

        http
                // 必須配置,不然OAuth2的http配置不生效----不明覺厲
                .requestMatchers()
                .antMatchers("/auth/login", properties.getLoginProcessUrl(), "/oauth/authorize")
                .and()
                .authorizeRequests()
                // 自定義頁面或處理url是,如果不配置全域性允許,瀏覽器會提示伺服器將頁面轉發多次
                .antMatchers("/auth/login", properties.getLoginProcessUrl())
                .permitAll()
                .anyRequest()
                .authenticated();
        
        // 表單登入
        http.formLogin()
                // 登入頁面
                .loginPage("/auth/login")
                // 登入處理url
                .loginProcessingUrl(properties.getLoginProcessUrl());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
  •  

到這裡已經完成了自定義登入頁的功能,接下來繼續說自定義授權頁面

5. 自定義授權頁面

自定義授權頁面的方式有兩種,分別如下;

(1). 直接定義如下controller 替換原來的授權controller

@Controller
// 必須配置
@SessionAttributes("authorizationRequest")
public class BootGrantController {

    @RequestMapping("/oauth/confirm_access")
    public ModelAndView getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception {
        AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest");
        ModelAndView view = new ModelAndView();
        view.setViewName("base-grant");
        view.addObject("clientId", authorizationRequest.getClientId());
        return view;
    }
}
  •  

(2). 在認證服務配置檔案中新增如下配置

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	......
	
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    	......
    	// 最後一個引數為替換之後頁面的url
        endpoints.pathMapping("/oauth/confirm_access","/custom/confirm_access");
    }
}
  •  

之後編寫對應的controller實現即可

6. 測試

最終效果如下
在這裡插入圖片描述

下一篇 Spring boot+Security OAuth2 爬坑日記(4)自定義異常處理 上

原始碼地址 Github