天天看點

24.Spring-Boot-Actuator與Spring-Security整合應用

      文章是指,在生産環境不是每一個使用者都可以檢視監控springboot應用的運作情況,通過整合spring security配置指定使用者通路Actuator。

     Spring Boot包含了一些額外的特性,可以幫助您在應用程式在上生産時監控和管理應用程式。您可以選擇使用HTTP管理監視您的應用程式。端點,帶有JMX,甚至是遠端shell (SSH或Telnet)。審計、健康和度量收集。可以自動應用到您的應用程式中。

       Actuator是Spring Boot提供的對應用系統的自省和監控的內建功能,可以檢視應用配置的詳細資訊,例如自動化配置資訊、建立的Spring beans以及一些環境屬性等。

Actuator的定義:

官方文檔:

An actuator is a manufacturing term, referring to a mechanical device for moving or controlling something. Actuators can generate a large amount of motion from a small change.

翻譯後:

執行器是制造術語,指移動或控制某物的機械裝置。執行器可以從一個小的變化産生大量的運動。

增加Actuator到你的maven工程中:

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

</dependencies>
           

在Spring MVC應用程式,Spring Boot Actuator 将自動配置所有啟用的端點通過HTTP公開。預設的約定是使用端點的id作為URL路徑。預設情況下,所有敏感的HTTP端點都是安全的,隻有具有執行器角色的使用者可以通路它們。具體Id介紹可參考官方文檔。

如果你在防火牆後面部署應用程式,你可能更喜歡所有的Actuator。可以在不需要身份驗證的情況下通路端點。

在application.properties中設定

management.security.enabled=false  這樣所有的使用者都可以用Actuator。

預設情況下,Actuator端點暴露在服務于正常HTTP的同一個端口上,即就是和你的應用端口是一緻的。

如果你的應用程式是公開部署的,你可能希望添加“Spring Security”來處理使用者身份驗證。當“Spring Security”被添加時,預設的“basic”身份驗證将被使用。

具體配置過程如下:

1.配置application.properties

#預設是沒有權限控制的,
#以下配置權限認證,隻有當使用者名是admin且密碼為123456,且擁有SUPERADMIN角色是才能通路
#預設角色為ACTUATOR
#對于密碼,生産上可以配置密文
management.security.enabled=true
security.user.name=admin
security.user.password=123456 
management.security.roles=SUPERADMIN
           

2.增加SecurityConfig.java類,配置spring-security

package com.niugang.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.builders.WebSecurity;
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;

@Configuration // 裡面已經包含了@Component 是以不用再上下文中在引入入了
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// spring自帶的
@Autowired
private UserDetailsService userDetailsService;


/**
* configure(HttpSecurity)方法定義了哪些URL路徑應該被保護
*/
@Override

protected void configure(HttpSecurity http) throws Exception {

                                 http.authorizeRequests()// 該方法所傳回的對象的方法來配置請求級别的安全細節
.antMatchers("/login").permitAll()// 登入頁面不攔截
.antMatchers(HttpMethod.POST, "/checkLogin").permitAll().anyRequest().authenticated()// 對于登入路徑不進行攔截
.and().formLogin()// 配置登入頁面
.loginPage("/login")// 登入頁面的通路路徑;
.loginProcessingUrl("/checkLogin")// 登入頁面下表單送出的路徑
.failureUrl("/login?paramserror=true")// 登入失敗後跳轉的路徑,為了給用戶端提示
.defaultSuccessUrl("/index")// 登入成功後預設跳轉的路徑;
.and().logout()// 使用者退出操作
.logoutUrl("/logout")// 使用者退出所通路的路徑,需要使用Post方式
.permitAll().logoutSuccessUrl("/login?logout=true")// 退出成功所通路的路徑
.and().csrf().disable();

}

/**
* 忽略靜态資源
*/


@Override
public void configure(WebSecurity web) throws Exception {
/*
* 在springboot中忽略靜态檔案路徑,直接寫靜态檔案的檔案夾
* springboot預設有靜态檔案的放置路徑,如果應用spring security,配置忽略路徑
* 不應該從springboot預設的靜态檔案開始
* 如:在本項目中,所有的js和css都放在static下,如果配置忽略路徑,則不能以static開始

* 配置成web.ignoring().antMatchers("/static/*");這樣是不起作用的,如果忽略靜态資源,頁面樣式可能無法加載

*/

web.ignoring().antMatchers("/themes/**","/script/**");
}

        /**
* 配置自定義使用者服務
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
// .passwordEncoder(passwordEncoder());
}
/**
* 密碼加密
*/
/*
* @Bean public BCryptPasswordEncoder passwordEncoder() { return new
* BCryptPasswordEncoder(); }
*/
}
           

3.添加UserDetailsServiceImpl.java,用于登入時進行資料庫認證

package com.niugang.service;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.niugang.bean.UserQuery;
import com.niugang.entity.User;
import com.niugang.exception.CheckException;
/**
 * 授權認證業務類
 * 
 * @author niugang UserDetailsService spring security包裡面的
 * 重寫loadUserByUsername方法
 *
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

       //UserService自定義的,從資料查詢資訊
@Resource
private UserService userService;


public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserQuery user = new UserQuery();
user.setName(username);
// 查詢使用者是否存在
List<User> queryList = userService.queryListByPage(user);
if (queryList != null & queryList.size() == 1) {
// 查詢使用者擁有的角色
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
//如果是admin使用者登入,授予SUPERADMIN權限
if(username.equals("admin")){
list.add(new SimpleGrantedAuthority("SUPERADMIN")); 
}

org.springframework.security.core.userdetails.User authUser = new org.springframework.security.core.userdetails.User(
queryList.get(0).getName(), queryList.get(0).getPassword(), list);


return authUser;
}
return null;

}
}
           

3.controller中添加代碼,使用者接受登入參數,調用認證服務

@Autowired(required=true)
private UserDetailsService userDetailsService;

         /**
* 跳轉到登入頁面
* 
* @param map
* @return
*/
  @RequestMapping(value = "/login", method = RequestMethod.GET)
   public String toLogin(ModelMap map,String paramserror ) {
if(paramserror!=null){
map.put("errorMessage", "使用者名或密碼錯誤");//認證失敗,用戶端傳回提示資訊
}
      return "view/login";
}

  @RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
public void  checkLogin(String username,String password) {
userDetailsService.loadUserByUsername(username);
}

4.登入頁面
           
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link href="themes/bootstrap.min.css" target="_blank" rel="external nofollow"  rel="stylesheet" />
<script type="text/javascript" src="script/jquery.min.js"></script>
<!--layer彈出框-->
<link rel="stylesheet" href="script/layer/mobile/need/layer.css" target="_blank" rel="external nofollow" >
<script type="text/javascript" src="script/layer/layer.js"></script>
</head>
<!-- -->
<style>
form {
width: 60%;
margin: 0 auto;
}
</style>
<body>
<form action="checkLogin" method='post'>
<h2  style="text-align:center">spring boot 
         </h2>
<div class="form-group">
<label for="name">姓名</label> <input type="text" class="form-control"
name="username" placeholder="姓名">
</div>
<div class="form-group">
<label for="password">密碼</label> <input type="password"
class="form-control" name="password" placeholder="密碼">
</div>
<button type="submit" id="btn_save"
class="btn btn-primary form-control">儲存</button>
</form>
<script type="text/javascript">
   <#if errorMessage??> 
layer.msg('${errorMessage}', {icon: 4,time:1000,anim: 6});
   
   </#if>

</script>
</body>
           

5.運作項目

登入頁面

24.Spring-Boot-Actuator與Spring-Security整合應用

登入認證失敗提示

24.Spring-Boot-Actuator與Spring-Security整合應用

通過非admin使用者登入,成功頁面

24.Spring-Boot-Actuator與Spring-Security整合應用

然後在位址欄輸入ACTUATOR 端點,提示通路拒絕,必須擁有SUPERADMIN角色權限

24.Spring-Boot-Actuator與Spring-Security整合應用

admin使用者登入,通路http://localhost:8080/myweb/mappings

24.Spring-Boot-Actuator與Spring-Security整合應用

通路http://localhost:8080/myweb/metrics

24.Spring-Boot-Actuator與Spring-Security整合應用

微信公衆号               

24.Spring-Boot-Actuator與Spring-Security整合應用

繼續閱讀