代码拉取完成,页面将自动刷新
springboot 整合 Spring Security
第一步:加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
一旦引入这个依赖,spring boot项目就默认开启了 security的默认保护。访问任何请求都会跳转到/login ,默认显示一个登录页面,但是我们并不知道用户名和密码。
用户名默认是user,密码是加密的 在运行后台可以找到,默认是打印到后来的。
第二步:java 配置类
package com.young.security.mysecurity.config;
import com.young.security.mysecurity.security.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
/**
* Create by stefan
* Date on 2018-05-17 21:23
* Convertion over Configuration!
*/
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private MyUserDetailService myUserDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//1.启用内存用户存储
// auth.inMemoryAuthentication()
// .withUser("xfy").password(passwordEncoder().encode("1234")).roles("ADMIN").and()
// .withUser("tom").password(passwordEncoder().encode("1234")).roles("USER");
//2.基于数据库表进行验证
// auth.jdbcAuthentication().dataSource(dataSource)
// .usersByUsernameQuery("select username,password,enabled from user where username = ?")
// .authoritiesByUsernameQuery("select username,rolename from role where username=?")
// .passwordEncoder(passwordEncoder());
//3.配置自定义的用户服务
auth.userDetailsService(myUserDetailService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/signIn").loginProcessingUrl("/user/userLogin") //自定义登录页面、登录请求路由
.and()
.logout().logoutSuccessUrl("/signIn")// 设置登出,登出成功后跳转到登录页面
.and()
.authorizeRequests() //开始请求的配置
.antMatchers("/signIn","/hello").permitAll() // premitAll()不做拦截
.antMatchers("/index").authenticated() //authenticated() 必须登录后可见
.antMatchers("/demo").permitAll()
.antMatchers("/admin/**","/add").hasRole("ADMIN") //有ADMIN角色
.regexMatchers("/admin1/.*").access("hasRole('ADMIN') or hasRole('ADMIN1')")
.anyRequest().authenticated()
.and()
.requiresChannel().antMatchers("/add").requiresSecure()//https://127.0.0.1:8443/add 将http转为https
.and()
.rememberMe().tokenValiditySeconds(2419200).tokenRepository(persistentTokenRepository()).alwaysRemember(true);// 启用记住我
}
// 记住我,将用户信息存入数据库
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
//tokenRepository.setCreateTableOnStartup(true);
return tokenRepository;
}
//注册密码加密处理器
@Bean
public static PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
自定义UserDetailsService
package com.young.security.mysecurity.security;
import com.young.security.mysecurity.pojo.Role;
import com.young.security.mysecurity.pojo.User;
import com.young.security.mysecurity.repository.RoleRepository;
import com.young.security.mysecurity.repository.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* Create by stefan
* Date on 2018-05-17 22:49
* Convertion over Configuration!
*/
@Component
@Slf4j
public class MyUserDetailService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
User user = userRepository.findByUsername(name);
if (user==null){
throw new AuthenticationCredentialsNotFoundException("authError");
}
log.info("{}",user);
List<Role> role = roleRepository.findByUsername(name);
log.info("{}",role);
List<GrantedAuthority> authorities = new ArrayList<>();
role.forEach(role1 -> authorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_"+role1.getRolename())));
log.info("{}",authorities);
return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities);
}
}
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)
@Secured({"ADMIN","ADMIN1"})
@RolesAllowed({"ADMIN","ADMIN1"})
使用方式相似,RolesAllowed更正式
@PreAuthorize("hasRole('ADMIN') AND hasRole('ADMIN1')") 的string参数是一个SpEL表达式
@PreAuthorize("hasRole('ADMIN') and #user.username.length() <=6") 可获得参数
@PostAuthorize("returnObject.username == principal.username") 可获得返回值
过滤方法
@PostFilter("hasRole('ADMIN') || filterObject.username == principal.username") 这个可直接获得方法的返回值列表的单个元素filterObject,不需要加#
@PreFilter("hasRole('ADMIN') || #filterObject.endsWith('admin')") 加#filterObject可获得传入参数列表的单个元素
视图保护(Thymeleaf)
第一步:引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
第二步:在视图页声明:
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
第三步使用:
<div sec:authorize="isAuthenticated()"> <!--sec:authorize属性会接受一个SpEL表达式 isAuthenticated() 只有用户已经进行认证了,才会渲染出内容。 -->
hello <span sec:authentication="name">someone</span> !
</div>
<form th:action="@{/logout}" method="post">
<input type="submit" value="注销"/>
</form>
<div sec:authorize="hasRole('ADMIN')">
会员admin可见
</div>
<div sec:authorize="hasRole('ADMIN') or hasRole('ADMIN1')">
会员admin\ADMIN1可见
</div>
<span sec:authorize-url="/admin/center">
<a th:href="@{/admin/center}">admin中心</a>
</span>
<span sec:authorize-url="/admin1/index">
<a th:href="@{/admin1/index}">admin1中心</a>
</span>
个人详细笔记整理: 让Spring Security 来保护你的Spring Boot项目吧
参考资料:
Spring Security 的使用才刚刚开始。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。