实习周记(三):学了一半的spring security,看了一遍的swagger,不太熟悉的定时与邮件

时间:2021-08-09
本文章向大家介绍实习周记(三):学了一半的spring security,看了一遍的swagger,不太熟悉的定时与邮件,主要包括实习周记(三):学了一半的spring security,看了一遍的swagger,不太熟悉的定时与邮件使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

SpringSecurity

提供了一套Web应用安全性的完整解决方案

用户认证

验证某个用户是否为系统中的合法主体,通俗意义上为系统验证用户是否能够登录

用户授权

验证某个用户是否有权限执行某个操作,在一个系统中,不同用户所就有的权限是不同的

特点

  1. 与spring结合性好
  2. 全面的权限控制
  3. 专门为web开发而设计
  4. 重量级(需要引入较多的依赖)

Demo

  1. 导入spring security依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.5.3</version>
</dependency>
  1. 编写controller
@Controller
public class logincontroller {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

正常会跳转至login页面,但是添加了spring security后,会跳转至验证界面,默认用户名为User,密码为控制台随机生成的密码

原理

实质上是一个过滤器链,重点有三个过滤器

FilterSecurityInterceptor

一个方法级的权限过滤器,位于过滤链的底端,控制方法是否能被访问

ExceptionTranslationFilter

异常过滤器,用于处理在认证授权过程中抛出的异常

UsernamePasswordAuthenticationFilter

对/login的post请求进行拦截,校验表单中的用户名和密码

加载过程

调用doFilter中的初始化方法,获取FilterChainProxy,并通过FilterChainProxy遍历加载器,放在集合中返回

接口

UserDetailsService

没有配置时,账号密码是由Spring security自定义生成的,为了满足业务需求,我们需要自定义逻辑控制认证逻辑

PasswordEncoder

数据加密接口,一般用于密码加密

Web权限方案

认证

先查询配置文件-->查询配置类-->查询实现了UserDetailsService接口的实现类

  1. 通过配置文件设置

    spring.security.user.name=???
    spring.security.user.password=???
    
  2. 通过配置类实现

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
       @Override
        protected void configure(AuthenticationManageBuilder auth) throws Exception{
             //加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123");
        auth.inMemoryAuthentication().withUser("chenchenchen").password(password).roles("admin");
        }
        
        //如果不创建此对象,会报错,找不到对应的对象
        @Bean
        PasswordEncoder password(){
            return new BCryptPasswordEncoder();
        }
    }
    
  3. 自定义实现类

    1. 创建配置类,设置使用哪个userDetailsService实现类
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
       @Autowired
        private UserDetailService userDetailService;
       @Override
        protected void configure(AuthenticationManageBuilder auth) throws Exception{
             //加密
            auth.userDetailsService(userDetailsService).passwordEncoder(password());
        }
        
        //如果不创建此对象,会报错,找不到对应的对象
        @Bean
        PasswordEncoder password(){
            return new BCryptPasswordEncoder();
        }
    }
    
    1. 编写实现类,返回User对象
    @Service
    public class MyUserDetailsService implements UserDetailsService{
        @Override
        public UserDetails loadUserByUsername(String s) throw UsernameNotFoundException{
            List<GrantedAuthority> auths = 
                AuthorityUtils.commaSeparatedStringToAuthorityList("role");
            return new User("chenchenchen",new BCryptPasswordEncoder().encode("123456"),auths)//auths为角色
        }
    }
    

权限

  1. 创建配置类
  2. 在配置类中设置拦截内容/在controller上使用注解设置权限

自动登录

实现

  1. 创建用户表

    CREATE TABLE `persistent_logins` (
     `username` varchar(64) NOT NULL,
     `series` varchar(64) NOT NULL,
     `token` varchar(64) NOT NULL,
     `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
    CURRENT_TIMESTAMP,
     PRIMARY KEY (`series`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. 配置类,注入数据源

    @Configuration
    public class BrowserSecurityConfig {
    @Autowired
    private DataSource dataSource;
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
     JdbcTokenRepositoryImpl jdbcTokenRepository = new
    JdbcTokenRepositoryImpl();
    // 赋值数据源
    jdbcTokenRepository.setDataSource(dataSource);
    // 自动创建表,第一次执行会创建,如果表存在则应当删除
    jdbcTokenRepository.setCreateTableOnStartup(true);
    return jdbcTokenRepository;
     }
    }
    

Swagger

  • 世界上最流行的Api框架
  • 前后端交流的工具
  • 即时生成Api文档
  • 可在线测试接口

Spring Boot整合Swagger

  1. 导入相应依赖包

    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-swagger2</artifactId>
       <version>2.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-swagger-ui</artifactId>
       <version>2.9.2</version>
    </dependency>
    
  2. 编写配置类

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        @Bean
        public Docket docket(){
            return  new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .enable(true)              //是否激活swagger
                    .groupName("陈晨橙")          //分组,可以设置多个docket
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.shaem.swagger.controller"))	//定义扫描的包
                //拦截除了shaem以外的接口
                    .paths(PathSelectors.ant("/shaem/**"))
                    .build();
        }
    
    
        public ApiInfo apiInfo(){
            return new ApiInfoBuilder()
                    .title("陈晨橙")
                    .description("test")
                    .version("1.0")
                    .termsOfServiceUrl("Url")
                    .contact(new Contact("name","url","email"))
                    .build();
        }
    }
    
    
  3. 重启项目,访问测试 http://localhost:8080/swagger-ui.html

配置API分组

  1. 默认为default,通过groupName()可以配置分组
  2. 可以通过配置多个Docket达到分组效果
@Bean
public Docket docket1(){
   return new Docket(DocumentationType.SWAGGER_2).groupName("group1");
}
@Bean
public Docket docket2(){
   return new Docket(DocumentationType.SWAGGER_2).groupName("group2");
}
@Bean
public Docket docket3(){
   return new Docket(DocumentationType.SWAGGER_2).groupName("group3");
}

实体类配置

  1. 使用ApiModel标识实体类
  2. 使用ApiModelProperty标识属性
  3. 只要请求接口返回值存在实体类,即会出现在文档中
@ApiModel("用户实体")
public class User {
   @ApiModelProperty("用户名")
   public String username;
   @ApiModelProperty("密码")
   public String password;
}
@RequestMapping("/getUser")
public User getUser(){
   return new User();
}

常用注解

下面列一些经常用到的,未列举出来的可以另行查阅说明:

Swagger注解 简单说明
@Api(tags = "xxx模块说明") 作用在模块类上
@ApiOperation("xxx接口说明") 作用在接口方法上
@ApiModel("xxxPOJO说明") 作用在模型类上:如VO、BO
@ApiModelProperty(value = "xxx属性说明",hidden = true) 作用在类方法和属性上,hidden设置为true可以隐藏该属性
@ApiParam("xxx参数说明") 作用在参数、方法和字段上,类似@ApiModelProperty

定时、异步与邮件

定时

spring提供两个接口让我们能实现定时执行任务的功能

  • Task Executor接口
  • Task Scheduler接口

在微服务中,我们通常使用注解来实现

  • @EnableScheduling(添加在启动类上)
  • @Scheduled(cron=“表达式”) //添加在想要执行的方法上

cron表达式

  一、结构

  corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份

  二、各字段的含义

字段 允许值 允许的特殊字符
秒(Seconds) 0~59的整数 , - * / 四个字符
分(Minutes 0~59的整数 , - * / 四个字符
小时(Hours 0~23的整数 , - * / 四个字符
日期(DayofMonth 1~31的整数(但是你需要考虑你月的天数) ,- * ? / L W C 八个字符
月份(Month 1~12的整数或者 JAN-DEC , - * / 四个字符
星期(DayofWeek 1~7的整数或者 SUN-SAT (1=SUN) , - * ? / L C # 八个字符
年(可选,留空)(Year 1970~2099 , - * / 四个字符

 注意事项:

  每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:

  (1)✳:表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

  (2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用,如果使用表示不管星期几都会触发,实际上并不是这样。

  (3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次

  (4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.

  (5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。

  (6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。

  (7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。

  (8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。

  (9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

异步

发送邮件一般不能立刻发送,让用户等待会降低体验,这个时候就可以用异步来模拟同步效果,让后台执行发送邮件的功能,其中涉及到多线程

  1. 在启动类上添加@EnableAsync
  2. 在方法上使用@Async
  3. 测试

邮件

在spring boot中使用邮件服务

  1. 引入依赖

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    
  2. 配置文件

    spring.mail.username=1435455332@qq.com
    #授权码可以在邮箱中的账号中找到
    spring.mail.password=qq授权码 
    spring.mail.host=smtp.qq.com
    # qq需要配置ssl
    spring.mail.properties.mail.smtp.ssl.enable=true
    
  3. 测试

     SimpleMailMessage message = new SimpleMailMessage();
       message.setSubject("通知-今晚早点下班");
       message.setText("今晚7:00下班");
    
       message.setTo("1435455332@qq.com");
       message.setFrom("1435455332@qq.com");
       mailSender.send(message);
    
     MimeMessage mimeMessage = mailSender.createMimeMessage();
       MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    
       helper.setSubject("通知");
       helper.setText("<b style='color:red'>今天 6:30下班</b>",true);
    
       //发送附件
       helper.addAttachment("1.jpg",new File(""));
       helper.addAttachment("2.jpg",new File(""));
    
       helper.setTo("1435455332@qq.com");
       helper.setFrom("1435455332@qq.com");
    
       mailSender.send(mimeMessage);
    

原文地址:https://www.cnblogs.com/cwtjyy/p/15119657.html