SpringSecurity整合SpringBoot集中式版

初步整合

首先创建springboot项目,并确保能够启动
编写一个处理器用于测试

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

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

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

启动项目,访问对应的地址:

测试成功

加入SpringSecurity的依赖

在SpringBoot中使用SpringSecurity不再像在Spring中那么麻烦,并不需要配置文件,只需要导入SpringSecurity的依赖即可

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

导入后重启,再次访问就需要进行认证了,这表明SpringSecurity已经生效了

那么问题来了!此刻并没有连接数据库,也并未在内存中指定认证用户,如何认证呢?
其实SpringBoot已经提供了默认用户名user,密码在项目启动时随机生成,如图:

复制随机生成的密码,使用user用户名登录即可

加入jsp页面

SpringBoot官方是不推荐在SpringBoot中使用jsp的,那么到底可以使用吗?答案是肯定的!
不过需要导入tomcat插件启动项目,不能再用SpringBoot默认tomcat了。

导入SpringBoot的tomcat启动插件依赖

<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>

加入jsp页面等静态资源

想要加入jsp页面,第一个需要解决的问题就是jsp页面放在哪儿?以前的resources是不能够再用来放jsp页面,因此需要再src/main下面创建webapp目录

这时webapp目录并不能正常使用,因为只有web工程才有webapp目录,在pom文件中修改项目为web工程

这时webapp目录,可以正常使用了!再导入自定义的jsp页面即可

修改相应的登录和退出地址

提供SpringSecurity配置类

以前想要SpringSecurity识别自己的登录页面需要去配置文件中配置,但是在SpringBoot这些配置都以配置类的形式存在,因此只需要创建配置类配置即可

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;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 认证用户的来源【内存或者数据库】
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}123")
                .roles("USER");
    }


    // 配置SpringSecurity相关信息
    @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()      // 释放上面所有的资源,例如/login是需要释放的
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.jsp")
                .invalidateHttpSession(true)      // 是否清空session
                .permitAll()
                .and()
                .csrf()
                .disable();      // 禁用csrf
    }
}

修改控制器

现在有了页面,就跳转到一个页面吧

@RequestMapping("/findAll")
public String findAll() {
    return "product-list";
}

配置视图解析器

我们需要指定前后缀,去application.yml中即可

使用tomcat插件启动项目



通过上面的方式启动页面。

此时可以看到,SpringSecurity已经开始使用我们自己的页面了。

加入数据库

数据库文件在[]: https://www.cnblogs.com/Myarticles/articles/12795346.html

导入相关包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>

在配置文件中添加数据库操作相关配置

在启动类上添加扫描mapper接口包注解

创建pojo对象

用户

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

@Data
public class SysUser implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Integer status;
    private List<SysRole> roles;

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public boolean isEnabled() {
        return true;
    }
}

角色

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;

@Data
public class SysRole implements GrantedAuthority {
    private Integer id;
    private String roleName;
    private String roleDesc;

    @JsonIgnore   // 标记此属性不做json处理
    @Override
    public String getAuthority() {
        return roleName;
    }
}

提供mapper接口

用户

import com.ericjin.springboot_security_jsp.domain.SysUser;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

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.ericjin.springboot_security_jsp.mapper.RoleMapper.findByUserId"))
    })
    SysUser findByName(String username);
}

角色

import com.ericjin.springboot_security_jsp.domain.SysRole;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

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}")
    List<SysRole> findByUserId(Integer uid);
}

提供认证service接口

import org.springframework.security.core.userdetails.UserDetailsService;

public interface UserService extends UserDetailsService {
}

提供认证service实现类

import com.ericjin.springboot_security_jsp.mapper.UserMapper;
import com.ericjin.springboot_security_jsp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

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

修改配置类

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;

    /**
     * 把加密对象放入IOC容器中
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 认证用户的来源【内存或者数据库】
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
}

使用mvn springboot:run的方式启动项目即可。
此时,整个项目就使用了数据库进行认证!

实现授权功能

在配置类上添加开启方法级的授权注解

在产品处理器类上添加注解

要求访问该方法必须拥有ROLE_PRODUCT角色

重启测试


显示403没有权限

指定自定义异常页面

import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class HandlerControllerException {

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

    @ExceptionHandler(RuntimeException.class)
    public String otherException() {
        return "forward:/500.jsp";
    }
}

再次测试就可以看到自定义异常页面了

到此,集中式环境中的整合就完成了!

posted @ 2020-05-01 16:53  Jin同学  阅读(213)  评论(0)    收藏  举报