1.搭建简单的springsecurity项目
参考文献:https://www.cnblogs.com/demingblog/p/10874753.html
第一步:引入security,jwt,fastjson的pom坐标
<!--springsecurity-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
第二步:创建一个controller
第三步:配置文件中配置用户名密码(不配置会有默认的用户名密码,默认的用户名是 user,密码则是一串 UUID 字符串,输出到了控制台日志里)
#springsecurity
spring.security.user.name=root
spring.security.user.password=root
第四步:启动项目,浏览器访问controller,会弹出登录框,用刚刚设置的用户名密码登录成功后会跳转到相应的controller,这种是HTTP Basic 认证的方式,接下来还有表单认证的方式。
2.自定义表单方式登陆
第一步:新建SecurityConfig类继承WebSecurityConfigurerAdapter,这个类主要是自定义安全方法,比如登陆方式,加密类型等
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//注入自定义的三个对象,下面附上该类代码
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationSuccessHandler successHandler;
@Autowired
private AuthenticationFailHandler failHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.authorizeRequests();
registry.and()
//表单登录方式
.formLogin()
.permitAll()
//成功处理类
.successHandler(successHandler)
//失败
.failureHandler(failHandler)
.and()
.logout()
.permitAll()
.and()
.authorizeRequests()
//任何请求
.anyRequest()
//需要身份认证
.authenticated()
.and()
//关闭跨站请求防护
.csrf().disable()
//前后端分离采用JWT 不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
//自定义使用自己定义的userDetailsService,连接数据库,设置加密类型
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
//设置加密类型
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
第二步:新建CustomUserDetailsService类继承UserDetailsService,自定义登陆规则。
@Component("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//这个方法里可以调用通过username查询数据库的方法
//User userFromDatabase = userRepository.findOneByLogin(login);
//if (userFromDatabase == null) {
//log.warn("User: {} not found", login);
//throw new UsernameNotFoundException("User " + login + " was not found in db");
//这里找不到必须抛异常
//}
//设置角色
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
//用加密方法给密码加密,注册的时候用
//BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
//String encode = bCryptPasswordEncoder.encode("root");
//这个密码是root加密后的密文,明文是root
return new User("root",new BCryptPasswordEncoder().encode("root"),grantedAuthorities);
}
}
第三步:新建AuthenticationSuccessHandler,登陆成功进入该方法
package com.wjn.security.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.ResponseUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
@Slf4j
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
String username = ((UserDetails)authentication.getPrincipal()).getUsername();
Collection<? extends GrantedAuthority> authorities = ((UserDetails) authentication.getPrincipal()).getAuthorities();
List<String> list = new ArrayList<>();
for(GrantedAuthority g : authorities){
list.add(g.getAuthority());
}
//登陆成功生成token
String token = UUID.randomUUID().toString().replace("-", "");
//token 需要保存至服务器一份,实现方式:redis or jwt输出到浏览器
Map<Object, Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","登陆成功");
map.put("username",username);
map.put("token",token);
PrintWriter out = response.getWriter();
response.setContentType("application/json; charset=utf-8");
response.setCharacterEncoding("UTF-8");
Object o = JSONObject.toJSON(map);
System.out.println(o);
out.print(o.toString());
}
}
第四步:新建AuthenticationFailHandler,登陆失败进入该方法
package com.wjn.security.handler;
import com.alibaba.fastjson.JSONObject;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Component
public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
// 默认情况下,不管你是用户名不存在,密码错误,SS 都会报出 Bad credentials 异常信息
Map<Object, Object> map = new HashMap<>();
if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
map.put("code",500);
map.put("msg","用户名或密码错误");
} else if (e instanceof DisabledException) {
map.put("code",500);
map.put("msg","账户被禁用,请联系管理员");
} else {
map.put("code",500);
map.put("msg","登录失败,其他内部错误");
}
PrintWriter out = response.getWriter();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
Object o = JSONObject.toJSON(map);
out.print(o.toString());
}
}
第五步:随便访问一个路径,进入登陆页面,然后输入正确的用户名密码或者错误的用户名密码会返回不同的json。