springsecurity

Spring Security-整合Spring Boot(原始

2022-05-17  本文已影响0人  石头耳东

零、本文纲要

一、快速入门
二、使用内存数据认证
三、连接数据库认证
四、授权管理

一、快速入门

1. 基础依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/>
</parent>

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

2. 配置文件application.yml

server:
  port: 8080

3. 启动类

@SpringBootApplication
public class SpringSecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityApplication.class, args);
    }
}

4. 表现层

@Controller
@RequestMapping("/product")
public class ProductController {

    @RequestMapping
    @ResponseBody
    public String findAll(){
        return "success";
    }
}

5. 测试

此时会跳出Spring Security默认的登录页面。

默认账户:user
默认密码:Using generated security password: 649253a1-3773-4c05-a480-1c08343928f2

注意:密码需要在启动后的控制台输出日志处查找。

二、使用内存数据认证

1. 添加整合JSP的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

2. 编写Security配置文件

@Configuration
@EnableWebSecurity
public class SecurityConfig {...}
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
        SpringWebMvcImportSelector.class,
        OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {

    boolean debug() default false;
}

在该注解的源码上方,官方提供了一个基础的配置类,具体如下:

@Configuration
@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
        // Spring Security should completely ignore URLs starting with /resources/
                .antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
                .hasRole("USER").and()
                // Possibly more configuration ...
                .formLogin() // enable form based log in
                // set permitAll for all URLs associated with Form Login
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
        // enable in memory based authentication with a user named "user" and "admin"
        .inMemoryAuthentication().withUser("user").password("password").roles("USER")
                .and().withUser("admin").password("password").roles("USER", "ADMIN");
    }

    // Possibly more overridden methods ...
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //认证用户的来源【内存 或者 数据库】
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        //此种写法是来自内存,来自数据库后面优化会提到
        auth.inMemoryAuthentication()
                .withUser("user").password("{noop}123456").roles("USER")
                .and()
                .withUser("admin").password("{noop}123456").roles("USER", "ADMIN");
    }

    //配置Spring Security的相关信息
    @Override
    public void configure(HttpSecurity http) throws Exception {
        //释放静态资源,指定资源拦截规则,指定自定义认证页面,指定退出认证配置,csrf配置
        http.authorizeRequests()
                .antMatchers("/login.jsp", "/failer.jsp", "/css/**", "/img/**", "/plugins/**").permitAll() //释放静态资源
                .antMatchers("/**").hasAnyRole("USER", "ADMIN") //拦截所有请求,需要"USER", "ADMIN"认证
                .anyRequest().authenticated() //其他请求需要认证通过才能访问
                .and()
                .formLogin() //配置自定义认证页面
                .loginPage("/login.jsp")
                .loginProcessingUrl("/login")
                .successForwardUrl("/index.jsp")
                .failureForwardUrl("/failer.jsp")
                .permitAll()
                .and()
                .logout() //配置退出认证
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.jsp")
                .invalidateHttpSession(true)
                .permitAll()
                .and()
                .csrf().disable(); //csrf配置
    }
}

3. 测试

通过Execute Maven Goal执行指令启动:spring-boot:run

三、连接数据库认证

1. 添加持久层所需依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--通用Mapper-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>

2. 编写配置

在application.yml处添加配置

server:
  port: 8080
spring:
  mvc:
    view:
      prefix: /pages/
      suffix: .jsp
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///security_authority?serverTimezone=UTC
    username: root
    password: 123456
mybatis:
  type-aliases-package: com.stone.domain
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.stone: debug

3. 编写实体类

public class SysRole implements GrantedAuthority {
    private Integer id;
    private String roleName;
    private String roleDesc;
    @JsonIgnore //此方法是实现规范的方法,并不是当前对象原有属性
    @Override
    public String getAuthority() {
        return roleName;
    }
    //省略了Get和Set方法
}
public class SysUser implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Integer status;
    private List<SysRole> roles;
    //省略了Get和Set方法
    //省略了重写方法
}

注意:在实体类重写的方法上添加@JsonIgnore注解

自定义的SysUser类直接实现UserDetails接口带来的好处:可以省去使用时的手动转换。

4. 编写Mapper类

public interface RoleMapper extends Mapper<SysRole> {
    @Select("select r.id, r.role_name roleName, r.role_desc roleDesc " +
            "from sys_role r, sys_user_role ur " +
            "where r.id = ur.rid and ur.uid = #{uid}")
    public List<SysRole> findById(Integer uid);
}
public interface UserMapper extends Mapper<SysUser> {
    @Select("select * from sys_user where username = #{username}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "roles", column = "id", javaType = List.class,
                    many = @Many(select = "com.stone.mapper.RoleMapper.findById"))
    })
    public SysUser findByName(String username);
}

5. 编写service接口及实现类

此处我们的接口需要继承UserDetailsService接口

public interface UserService extends UserDetailsService {
}
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userMapper.findByName(username);
    }
}

6. 修改认证对象来源

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    //认证用户的来源【数据库】
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //注意:configure方便不变,此处省略
}

7. 测试

四、授权管理

1. @EnableGlobalMethodSecurity

此处可以参考Spring Security-原始篇(XML配置版)功能优化篇中权限管理-注解说明的介绍。

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ GlobalMethodSecuritySelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableGlobalMethodSecurity {
    
    boolean prePostEnabled() default false;

    boolean securedEnabled() default false;

    boolean jsr250Enabled() default false;

    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default Ordered.LOWEST_PRECEDENCE;
}

2. 添加授权

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true) //开启SpringSecurity注解支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {...}
@Service
public class ProductServiceImpl implements ProductService {
    @Secured({"ROLE_ADMIN","ROLE_PRODUCT"})
    @Override
    public String findAll() {
        return "product-list";
    }
}

3. 统一异常处理

@ControllerAdvice
public class HandlerControllerException {

    @ExceptionHandler(AccessDeniedException.class)
    public String handleAccessDeniedException(){
        return "redirect:/403.jsp";
    }

    @ExceptionHandler(Throwable.class)
    public String handleThrowable(){
        return "redirect:/500.jsp";
    }
}

4. 测试

五、结尾

以上即为Spring Security-整合Spring Boot(原始篇-单体架构)的基础内容,感谢阅读。

上一篇 下一篇

猜你喜欢

热点阅读