Spring Boot . 4 -- 定制 Spring Boot 配置

  • 覆写 Auto-Configuration 的类
  • 利用外部属性进行动态配置 【本文】
  • 定制 Error 页面 【第二篇】

    Spring Boot的自动配置可以节省很多无趣的配置工作,但是并不是所有的自动配置都能满足需求。比如链接数据库的时候,需要使用一些OR-Mapping 的中间件;比如安全相关的配置需要针对不用的场景/应用/业务进行定制化的开发和配置;或者需要根据不同的运行时条件,做不同的分支决策;等等。所以Sping Boot 提供了两种基本方式,允许开发者对现有的自佛那个配置进行定制化的更改:配置覆写、细粒度的外部属性配置。【explicit configuration overrides、fine-grained configuration with properties】

    覆写(Override)Spring Boot 的自动配置

    覆写配置可以采用Spring支持的任意一种配置方式:XML、Groovy 脚本、Java 代码 等。这里使用Java代码方式的配置。WebSecurityConfigurerAdapter 提供了覆写SecurityConfig 的入口。做这样的假定:(1)只在登录页面做登录校验,其他页面不进行校验;(2)登陆账户和密码是 user-password;(3)登录这的角色为 USER。

    首先定义一个Controller响应Http请求。响应登录、查看登录状态、登出 等Http请求。    

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    @Autowired
    private ReaderRepository readerRepository;

    @RequestMapping(value = "/addUser")
    public String addUser()
    {
        // 向数据库中加入一个User
        Reader reader = new Reader();
        reader.setFullname("pa");
        reader.setPassword("password");
        reader.setUsername("user");
        readerRepository.save(reader);
        return "index";
    }

    @RequestMapping("/")
    public String index() {
        readerRepository.saveAndFlush(new Reader("user","password","password"));
        return "index";
    }

    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

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

    实现自主配置的 安全校验是通过 继承和覆写 WebSecurityConfiguerAdapter 类来实现的,指定需要进行安全校验的类,指定进行校验的数据等,代码如下:

package readinglist;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

@Configuration
@EnableWebSecurity  // 这个注解启用了定制的安全配置 安全的校验机制按照被注解类的逻辑进行
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ReaderRepository readerRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/").permitAll()  // "/" 这个路径下不进行安全校验
                .anyRequest().authenticated()  // 其他的路径均需要校验
                .and()
                .formLogin()
                .loginPage("/login")           // 默认的登录页面
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

// 在这里进行登录校验,通过数据库来进行 用户名和密码的 校验 @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(new UserDetailsService() { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return readerRepository.findOne(username); } }); } public void setReaderRepository(ReaderRepository readerRepository) { this.readerRepository = readerRepository; } }

     以上就是最核心的代码。其他的自主配置的方式基本一致。

     辅助的代码:Reader 的定义。

     

package readinglist;

import java.util.Arrays;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
public class Reader implements UserDetails {
    private static final long serialVersionUID = 1L;

    @Id
    public String username;
    public String fullname;
    public String password;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("USER"));
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getFullname() {
        return fullname;
    }
    public void setFullname(String fullname) {
        this.fullname = fullname;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

      Repository 的代码: 

package readinglist;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ReaderRepository extends JpaRepository<Reader, String> {
}

        

posted on 2017-01-16 21:44  来也  阅读(1249)  评论(0编辑  收藏  举报