springboot+springsecurity基础配置(二)

继续上一篇博客的项目,向下扩展

 

springsecurity中所有配置基本都来源于一个默认的WebSecurityConfigurerAdapter

所以我们要写一个类来继承它,放弃默认配置

叫SecurityConfig

 

添加一个login.html登录页面,登录成功以后跳到之前写的hello.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login page</title>
</head>
<body>
This is login page
<form action="/login" method="post">
    username: <input name="username" /><br/>
    password: <input name="password" /><br/>
    <button type="submit">submit</button>
</form>
</body>
</html>

这个提交地址/login比较有意义,后面会用到配置

然后我们开始配置SecurityConfig

package com.security.securitydemo.security;

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.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @Author WQY
 * @Date 2019/11/27 9:44
 * @Version 1.0
 */
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表单提交的一直必须一样,这样才能让springsecurity帮你处理请求
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                //添加不需要过滤的地址
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated();
    }

}

 

然后启动项目访问http://localhost:8880

就会出现自定义的登录界面

然后输入用户名密码后会出现403

不急别慌,因为开启了debug所以能在控制台看见走了一个CrsfFilter,这个filter需要一个参数,防止xss攻击的,但是我们不需要,所以我们禁掉。

修改SecurityConfig。

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表单提交的一直必须一样,这样才能让springsecurity帮你处理请求
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();
    }

在登陆就不会有403的错误了

但是会出现404的错误

因为没有设置登录成功的页面,所以http://localhost:8080作为了默认页面

然后我们在

SecurityConfig

中添加一个登录成功页面

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表单提交的一直必须一样,这样才能让springsecurity帮你处理请求
                .loginProcessingUrl("/login")
                .successForwardUrl("/hello")
                .and()
                .authorizeRequests()
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();
    }

可是这样我这会出现405

在修改SecurityConfig文件,添加默认成功页面

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")//处理登录请求接口
                .successForwardUrl("/hello")
                .defaultSuccessUrl("/hello",true)
                .and()
                .authorizeRequests()
                .antMatchers("/index","/login","/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();

    }

这样输入账号密码后就进来了

 

自定义数据查询

经过上面的配置,我们实现了自定义登录页,但是数据是写死的

所以现在要从数据库获取用户信息

比如我们的数据库一共有两张表,user表和role表

package com.security.securitydemo.entity;


import lombok.Data;

import javax.persistence.*;
import java.util.Date;

/**
 * @Description  
 * @Author  WQY
 * @Date 2019-11-05 
 */
@Data
@Entity
@Table ( name ="user" )
public class UserEntity{

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
   	@Column(name = "id" )
	private Long id;

	/**
	 * 用户名
	 */
   	@Column(name = "username" )
	private String username;

	/**
	 * 密码
	 */
   	@Column(name = "password" )
	private String password;

	/**
	 * 保存时间
	 */
   	@Column(name = "savetime" )
	private Date savetime;

	/**
	 * 手机号
	 */
   	@Column(name = "iphone" )
	private String iphone;

	/**
	 * 权限
	 */
   	@Column(name = "authority" )
	private Long authority;

	/**
	 * 性别,1男,2女
	 */
   	@Column(name = "sex" )
	private String sex;

	/**
	 * 组织机构编号
	 */
   	@Column(name = "organization_num" )
	private String organizationNum;

	/**
	 * 组织机构名称
	 */
   	@Column(name = "organization_name" )
	private String organizationName;
}
package com.security.securitydemo.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * @Description  
 * @Author  WQY
 * @Date 2019-11-25 
 */
@Data
@Entity
@Table ( name ="role" )
public class RoleEntity  {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
   	@Column(name = "id" )
	private Long id;

   	@Column(name = "name" )
	private String name;


}

并建立他们的Repository

package com.security.securitydemo.dao;


import com.security.securitydemo.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author WQY
 * @date 2019/9/9 15:28
 */
public interface User_Jpa extends JpaRepository<UserEntity,Integer> {

    UserEntity findByUsername(String username);

}
package com.security.securitydemo.dao;


import com.security.securitydemo.entity.RoleEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

/**
 * @Author WQY
 * @Date 2019/11/25 17:10
 * @Version 1.0
 */
public interface Role_Jpa extends JpaRepository<RoleEntity,Long> {

    @Query(value = "select d from RoleEntity d where d.id=?1")
    RoleEntity selectById(Long id);
}

基础项写完以后就要与sprinsecurity结合了

springsecurity中对于用户的表示有自己的实体类相对应,它就是UserDetails,所以我们编写一个AuthUser实现这个接口:

package com.security.securitydemo.security.entity;

import com.security.securitydemo.entity.RoleEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author WQY
 * @Date 2019/11/26 14:52
 * @Version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AuthUser implements UserDetails {

    private String username;
    private String password;
    private List<RoleEntity> roles;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles.isEmpty() ? Collections.EMPTY_LIST :
// ROLE_ 是springsecurity对于角色的默认前缀,如果不加,验证会失败
                (roles.parallelStream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList()));    }

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

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

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

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

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

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

其中关于账号过期,enable全部设置为通过,接下来就是编写CustomUserDetailsService,返回我们自己的AuthUser:

package com.security.securitydemo.security.impl;


import com.security.securitydemo.dao.Role_Jpa;
import com.security.securitydemo.dao.User_Jpa;
import com.security.securitydemo.entity.UserEntity;
import com.security.securitydemo.security.entity.AuthUser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;

/**
 * @Author WQY
 * @Date 2019/11/26 14:55
 * @Version 1.0
 */
@Service
@Primary
public class CustomUserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private User_Jpa userRepository;

    @Resource
    private Role_Jpa roleRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity user = userRepository.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("user: " + username + " is not found.");
        }

        return new AuthUser(user.getUsername(), user.getPassword(), roleRepository.findAllById(Collections.singletonList(user.getAuthority())));
    }

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

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        System.out.println(bCryptPasswordEncoder.encode("123456"));
    }

}

到此,其实我们的UserDetails已经注入了Spring中,其实我们加上@Service和@Primary之后,springsecurity就能自己检测到这个bean,然后作为自己的UserDetailsService。

因为加了加密,所以先用main方法对123456加密,然后放入数据库

最后是一个修改controller

package com.security.securitydemo.controller;

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

/**
 * @Author WQY
 * @Date 2019/11/27 9:31
 * @Version 1.0
 */
@Controller
@RequestMapping
public class HelloController {

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

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

    @RequestMapping("/index")
    public String index() {
        return "/index.html";
    }
}

然后在访问页面输入admin和123456(自己定义以后的)

就会进入hello.html页面,由于在

SecurityConfig

中配置了几个放行的页面所以直接访问http://localhost:8880/index也行

因为他不需要权限

项目地址:https://download.csdn.net/download/qq_41755287/12000491

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章