zoukankan      html  css  js  c++  java
  • 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" rel="stylesheet" />
    <script type="text/javascript" src="script/jquery.min.js"></script>
    <!--layer弹出框-->
    <link rel="stylesheet" href="script/layer/mobile/need/layer.css">
    <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.运行项目

    登录页面

    登录认证失败提示

    通过非admin用户登录,成功页面

    然后在地址栏输入ACTUATOR 端点,提示访问拒绝,必须拥有SUPERADMIN角色权限

    admin用户登录,访问http://localhost:8080/myweb/mappings

    访问http://localhost:8080/myweb/metrics

     微信公众号

     

     

  • 相关阅读:
    C# DataTable 和List之间相互转换的方法
    毫秒级百万数据分页存储过程(mssql)
    lambdas vs. method groups
    关于优化C#程序的五十种方法
    Retrieving failed records after an SqlBulkCopy exception
    将数字按照3位一组添加逗号的正则替换
    生成互不相同随机数的一种算法
    2018年ElasticSearch6.2.2教程ELK搭建日志采集分析系统(教程详情)
    2018年ElasticSearch6.2.2教程ELK搭建日志采集分析系统(目录)
    JMeter接口压力测试课程入门到高级实战
  • 原文地址:https://www.cnblogs.com/niugang0920/p/12196400.html
Copyright © 2011-2022 走看看