在springboot项目里面,一般是不建议使用jsp页面的,但是还是可以使用的,我们通过springboot的启动类进行启动项目,是不识别jsp页面的,所以不同通过启动类进行启动,现在我们要使用其他的方法

1 导入一个启动插件的依赖

  <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 因为要使用jsp,所以创建一个webapp的目录,在这个里面放jsp页面,但是创建的webapp的目录是不能识别的,没有蓝色的点,现在就需要在pom里面加这个


这样webapp就变为蓝色的标志了,里面就可以放东西了,记住,这个里面现在只是放前端的东西就可以了,不需要手动自己写web.xml这个配置了。


以上只是将jsp页面导入到了项目里面,但是还没有在项目里面进行使用,也就是还不能被springsecurity框架进行识别。我们需要配置之后才可以识别。

springboot项目没有xml文件,所以一般是写配置类

自己写一个配置类,加上这个注解
@EnableWebSecurity
继承这个springsecurity框架里面的类WebSecurityConfigurerAdapter
只有加上这个注解,继承了这个,里面才可以写关于springsecurity相关的东西。


也就是以上的3个地方,都要按照人家的规则写,这样就相当于写一个springsecurity的配置了,这个类相当于springsecurity.xml 这个配置类里面什么也可以不写,不写就是默认的,因为继承了人家源码里面的类。

我们不想要默认的,想要自定义的,所以要重写人家的方法。

回顾之前的springsecurity.xml里面配置过什么

1 释放静态资源

2 把加密对象放入的IOC容器中

3 认证的数据的来源


4 配置认证信息

在配置类里面重写人家的方法,在方法里面写自定义的东西

重写的方法是configure() 只是里面的参数不一样,在这两个方法里面写自己的东西就可以了

configure(HttpSecurity http)这个方法里面配置的东西和以前的一样,都是配置

1 释放静态资源
2 指定资源拦截规则
2 指定自定义的页面
3 指定退出的认证规则
4 csrf的配置

  //指定认证对象的来源,这个数据来源是数据库
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
   
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    //SpringSecurity配置信息
    public void configure(HttpSecurity http) throws Exception {
   
        http.authorizeRequests()
                1 释放静态资源
                .antMatchers("/login.jsp", "failer.jsp", "/css/**", "/img/**", "/plugins/**").permitAll()
                2 这个接口要这个角色
                .antMatchers("/product").hasAnyRole("USER")
                3 其他的资源只有认证通过之后才可以通过
                .anyRequest().authenticated()
                4 这个and表示新的开始
                .and()
                .formLogin()
                5 表示要认证这个页面
                .loginPage("/login.jsp")
                6 提交的时候走的路径
                .loginProcessingUrl("/login")
                7 认证成功之后跳转到的页面
                .successForwardUrl("/index.jsp")
                8 认证失败之后跳转的页面
                .failureForwardUrl("/failer.jsp")
                .and()
                .logout()
                10 退出的时候走的路径
                .logoutSuccessUrl("/logout")
                11 退出的时候是否清session
                .invalidateHttpSession(true)
                11 退出成功之后跳转的页面
                .logoutSuccessUrl("/login.jsp")
                .and()
                12 不让csrf起作用
                .csrf()
                .disable();
    }

还有将加密对象放到容器里面

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
   
        return new BCryptPasswordEncoder();
    }

以上就是将关于springsecurity的配置写完了,现在开始测试

我们写一个controller,

但是我们看这个controller的返回,这个应该是springmvc给我们自动的加前缀和后缀,之后跳转到对应的页面。

这个视图解析器我们是可以自己配置的,自己定义前缀和后缀。在yml里面配置


以上配置了之后,我们就在controller里面的返回上面不需要写全路径了。

以上就完全配置完了,现在要启动,但是不能用启动类进行启动了,用pom里面自己配置的tomcat的jar包进行启动。


以上就可以在浏览器输入路径了,就可以看见跳转到了我们自己定义的登录的页面,输入用户名和密码之后才可以到首页

连接数据库

1 导入数据库的jar包

2 在yml里面配置数据源的用户名和密码


mybatis:
  type-aliases-package: com.itheima.domain  给实体类起别名
  configuration:
    map-underscore-to-camel-case: true   开启驼峰命名
logging:
  level:
    com.itheima: debug   打开日志

以上就可以连接数据库了,

完成连接数据库的认证操作

因为springsecurity框架的自定义的认证需要返回的对象是框架自己的,之前我们是在业务层从数据库里面查询出用户的信息,自己转成人家的UserDetails对象返回。现在我们使用另外一个方法,直接在实体类继承这个UserDetails对象,以后直接返回我们自己的实体类就可以了。

1 创建用户信息的实体类,继承UserDetails

@JsonIgnore  这个的意思是在转化为json格式的时候,这个字段就不参与了
public class SysUser implements UserDetails {
   

    private Integer id;
    private String username;
    private String password;
    private Integer status;
    private List<SysRole> roles;

    public List<SysRole> getRoles() {
   
        return roles;
    }

    public void setRoles(List<SysRole> roles) {
   
        this.roles = roles;
    }

    public Integer getId() {
   
        return id;
    }

    public void setId(Integer id) {
   
        this.id = id;
    }

    public void setUsername(String username) {
   
        this.username = username;
    }

    public void setPassword(String password) {
   
        this.password = password;
    }

    public Integer getStatus() {
   
        return status;
    }

    public void setStatus(Integer status) {
   
        this.status = status;
    }
  @JsonIgnore  这个的意思是在转化为json格式的时候,这个字段就不参与了
    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
   
        return roles;
    }

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

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

    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
   
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
   
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
   
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isEnabled() {
   
        return true;
    }
}

角色的实体类
@JsonIgnore 这个的意思是在转化为json格式的时候,这个字段就不参与了

@JsonIgnore 这个的意思是在转化为json格式的时候,这个字段就不参与了

public class SysRole implements GrantedAuthority {
   

    private Integer id;
    private String roleName;
    private String roleDesc;

    public Integer getId() {
   
        return id;
    }

    public void setId(Integer id) {
   
        this.id = id;
    }

    public String getRoleName() {
   
        return roleName;
    }

    public void setRoleName(String roleName) {
   
        this.roleName = roleName;
    }

    public String getRoleDesc() {
   
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
   
        this.roleDesc = roleDesc;
    }
  @JsonIgnore  这个的意思是在转化为json格式的时候,这个字段就不参与了
    @JsonIgnore
    @Override
    public String getAuthority() {
   
        return roleName;
    }
}

2 创建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> findByUid(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.itheima.mapper.RoleMapper.findByUid"))
    })
    public SysUser findByName(String username);

}

3 写业务层


@Service
@Transactional
public class UserServiceImpl implements UserService {
   

    @Autowired
    private UserMapper userMapper;

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

}

在springsecurity的配置类的里面的数据源变为这个业务层

    //指定认证对象的来源
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
   
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

以上就完成了用数据库作为数据源,自定义的登录页面的功能