一,整合进依赖
每个依赖都标了注释,大家可以按照自己需要的来添加,置于配置问件啥的,大家可以参考springboot+mybatisplus+redis整合(附上脚手架完整代码)
<!--主要就是加了这个依赖-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--web 启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--模板引擎thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<!--mybatis-plus以及生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.29</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<!--lombok用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
二,配置过滤规则(类似配置shiro中的ShiroFilterFactoryBean)
大致内容:配置一些登录的跳转,及权限、登录验证的跳转规则。和记住我实现自动登录的配置。
/**
* @author 张子行
* @class WebSecurityConfigurerAdapter
*/
@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
//注入数据源
@Autowired
private DataSource dataSource;
/**
* @param
* @method 配置登录记住我,记住我相关的底层数据库的相关配置,生成的token存储在里面
*/
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//开启后token会存储在这张表里面
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
/**
* @param
* @method 配置授权认证逻辑
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
/**
* @param
* @method 密码加密规则
*/
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
/**
* @param
* @method 配置过滤规则 url层面
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//退出
http.logout().logoutUrl("/logout").
logoutSuccessUrl("/test/hello").permitAll();
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
http.authorizeRequests()
.antMatchers("/", "/test/hello", "/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
//当前登录用户,只有具有admins权限才可以访问这个路径
//1 hasAuthority方法
// .antMatchers("/test/index").hasAuthority("admins")
//2 hasAnyAuthority方法
// .antMatchers("/test/index").hasAnyAuthority("admins,manager")
//3 hasRole方法 ROLE_sale
.antMatchers("/test/index").hasRole("sale")
.anyRequest().authenticated();
//配置 登录的相关
http.formLogin() //自定义自己编写的登录页面
.loginPage("/on.html") //登录页面设置
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/success.html").permitAll() //登录成功之后,跳转路径
.failureUrl("/unauth.html");
//配置 自动登录记住我
http.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60).userDetailsService(userDetailsService);
//关闭csrf防护
http.csrf().disable();
}
}
三,编写登录认证逻辑
大体逻辑:根据用户名查询用户信息,及其权限返回
/**
* @author 张子行
* @class UserDetailsService
*/
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UsersMapper usersMapper;
/**
* @param
* @method 登录逻辑
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//调用usersMapper方法,根据用户名查询数据库
QueryWrapper<User> wrapper = new QueryWrapper();
// where username=?
wrapper.eq("username", username);
User user = usersMapper.selectOne(wrapper);
//判断
if (user == null) {//数据库没有用户名,认证失败
throw new UsernameNotFoundException("用户名不存在!");
}
//角色要加前缀ROLE_ ,权限直接没啥要求
List<GrantedAuthority> auths =
AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale");
//从查询数据库返回users对象,得到用户名和密码,返回
return new org.springframework.security.core.userdetails.User(user.getUsername(),
new BCryptPasswordEncoder().encode(user.getPassword()), auths);
}
}
四,编写html页面
主要写下登录页面,注意这里的action="/user/login"就是我们配置过的登录的请求action
<h1>static表单提交11</h1>
<!-- 表单提交用户信息,注意字段的设置,直接是*{} -->
<form action="/user/login" method="post">
<input type="text" name="username"/>
<input type="text" name="password"/>
<input type="checkbox" name="remember-me"/>自动登录
<input type="submit"/>
</form>
五,编写controller
大体对以下的注解做了个测试
注解 | 作用 | 可选参数 |
@PreAuthorize | 在入方法之前拦截 | hasPermission(),hasRole(),hasAnyAuthority(),hasAnyRole(),hasAuthority() |
@PostAuthorize | 在出方法之前拦截 ,如果没有相关权限,虽执行方法但是还是没有通过认证,返回页面显示没有权限 | hasPermission(),hasRole(),hasAnyAuthority(),hasAnyRole(),hasAuthority() |
@PostFilter | 只返回指定的model信息 | filterObject.username == ‘zzh’ |
/**
* @author 张子行
* @class TestController
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("hello")
public String hello() {
return "hello security";
}
@GetMapping("index")
public String index() {
return "hello index";
}
@GetMapping("update")
//@Secured({"ROLE_sale","ROLE_manager"})
@PreAuthorize("hasAnyAuthority('admins')")
@PostAuthorize("hasAnyAuthority('admins1')")
public String update() {
System.out.println("update......");
return "hello update";
}
@GetMapping("getAll")
@PostAuthorize("hasAnyAuthority('admins')")
@PostFilter("filterObject.username == 'admin1'")
public List<User> getAllUser(){
ArrayList<User> list = new ArrayList<>();
User user = new User();
user.setId(1);
user.setPassword("666");
user.setUsername("zzh");
list.add(user);
return list;
}
}
六,测试
1:输入任何url都要求登录
2:点登录提交,登录名密码错误或者为空都登不进
3:登录成功,可以正常访问那些页面喽,关闭浏览器,重新进入那些需要权限的页面,无需再次登录即可进去,记住我功能成功
4:自动生成的token表有数据
觉着不错的点个小星星吧,爱你哟!