SpringSecurity的简单使用
SpringSecurity是基于Spring应用提供的声明式的安全保护性的框架,它可以在web请求级别的和方法调用级别处理身份和授权。
1.引入SpringSecurity
创建maven项目引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.UserDetailsService的使用
当登录时,需要对传来的的参数进行验证,检测传来的用户名及密码是否正确,这时候就需要用UserDetailsService验证用户名、密码和授权。
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
//根据用户名进行查询 查询不到则报错
if (!"admin".equals(userName)){
throw new UsernameNotFoundException("用户名错误");
}
//模拟从数据库中取出加密后的密码
String password=passwordEncoder.encode("123456");
//返回查询结果 返回的User是springsecurity的类,
return new User(userName,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_abc"));
}
实现UserDetailsService接口,根据用户名查出密码和权限等其他信息,封装成User类返回,若用户名和密码等信息和前端传来的信息一致,则登陆成功,否则失败。
3.WebSecurityConfigurerAdapter类参数设置
登录成功或者失败,我们都需要设置跳转页面或者给某个页面能否访问设置权限。这就需要WebSecurityConfigurerAdapter类进行参数设置,一些常用的设置参数如下:
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccessDeniedHandler accessDeniedHandler;
@Bean
public PasswordEncoder getPe(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单提交
http.formLogin()
//自定义入参:设置表单的参数名称
.usernameParameter("userName")
.passwordParameter("password")
//自定义登陆页面 确定哪个页面是登陆页面
.loginPage("/login.html")
//自定义登录逻辑,必须和表单提交接口一样,执行自定义登录逻辑
.loginProcessingUrl("/login")
//登陆成功后跳转页面,必须为post请求
.successForwardUrl("/toMain")
//自定义的登录成功处理器
// .successHandler(new MySuccessUrlHandler("http://www.baidu.com"))
//失败跳转登陆页面 post请求
.failureForwardUrl("/toError");
//授权 所有请求必须经过认证
//设置不需要认证的页面
http.authorizeRequests().antMatchers("/login.html").permitAll()
.antMatchers("/error.html").permitAll()
//基于权限认证 若有叫做“admin”的权限才可访问该页面
//.antMatchers("/main1.html").hasAnyAuthority("admin")
//基于角色认证
.antMatchers("/main1.html").hasRole("abcd")
//基于ip地址认证
//.antMatchers().hasIpAddress("");
//上述各种方法都是基于access
//.antMatchers().access("hasRole('abc')")
//设置除了上述页面外,其他页面的访问皆需权限认证
.anyRequest().authenticated();
http.csrf().disable();
//自定义异常处理器
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
}
自定义的登录成功处理器如下,登陆成功后会执行该方法:
public class MySuccessUrlHandler implements AuthenticationSuccessHandler {
private String url;
public MySuccessUrlHandler(String url) {
this.url = url;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.sendRedirect(url);
}
}
自定义的异常处理器如下:
@Component
public class MyAccessDenisHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setHeader("Context-Type","application/json");
PrintWriter printWriter=httpServletResponse.getWriter();
printWriter.write("{\"msg\":\"权限不足\"}");
printWriter.flush();
printWriter.close();
}
}
1.@Secured()的使用
该注解可使用在controller或service上,但controller指定了接口,一般用于controller上,该注解是判断是否具有角色的,参数以"ROLE_"开头,若条件不允许,则报500错误。
开启注解配置:@EnableGlobalMethodSecurity(securedEnabled = true)
@Secured("ROLE_ab")
2.@PreAuthorize()和@PostAuthorize()的使用
该注解和@Secured()相同,只不过是使用access表达式判断,@PreAuthorize()是在执行操作前判断,@PostAuthorize()是在执行后判断,因此使用较少。
开启注解配置:@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@PreAuthorize("hasRole('ROLE_ab')")
3.Remenber-me功能的实现
该功能将用户数据存储到数据源中,一段时间内不用登录进行访问。该功能需要配置数据库和数据库连接池,
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
在权限配置类中的configure()方法中对remmber-me功能进行设置:
//remenber me
*持久化token
* Security中,默认是使用PersistentTokenRepository的子类InMemoryTokenRepositoryImpl,将token放在内存中
* 如果使用JdbcTokenRepositoryImpl,会创建表persistent_logins,将token持久化到数据库
http.rememberMe().tokenRepository(persistentTokenRepository) //设置超时时间 .tokenValiditySeconds(60) //设置自定义登录逻辑 .userDetailsService(userDetailService);
JdbcTokenRepositoryImpl设置如下:
@Bean
public PersistentTokenRepository getPersistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository=new JdbcTokenRepositoryImpl();
//设置数据源
jdbcTokenRepository.setDataSource(dataSource);
//自动建表,第一次启动开启,以后注释掉
//dbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
登陆页面中的remember-me功能:
记住<input type="checkbox" name="remember-me" value="true" ><br/>
5.退出登录
//退出登录
http.logout()
//退出成功到的url
.logoutSuccessUrl("/login.html")
//自定义退出登录接口
.logoutUrl("/mylogout");

浙公网安备 33010602011771号