(本文属于基础,对于各种过滤器不在深究,想研究的道友可以查看其它资料,本文更多的简单说一下ss框架的大体流程,偏向应用)
org.springframework.cloud
spring-cloud-security
org.springframework.boot
spring-boot-starter-thymeleaf
@Controller
public class hello {
@RequestMapping("/login")
public String hello(){
return "/login";
}
@RequestMapping("/user")
public String hello1(){
return "/user";
}
@RequestMapping("/admin")
public String hello2(){
return "/admin";
}
}
@Configuration
public class text extends WebSecurityConfigurerAdapter {
/**
* 重写该方法,设定用户访问权限
* 这里的http对象最终要做的事就是把对应的url-role进行映射并应用到过滤链中
* */
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user").hasRole("USER") //用户权限
.antMatchers("/admin").hasRole("ADMIN") //管理员权限
.antMatchers("/login").permitAll() //所有用户都可以访问
.and()
.formLogin();
}
/**
* 重写该方法,添加自定义用户
* 自定义我们的用户和角色
* */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("pk1").password("123").roles("USER")
.and()
.withUser("pk2").password("123").roles("ADMIN");
}
}
//不进行密码加密
@Bean
public static PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
public abstract Authentication attemptAuthentication(HttpServletRequest var1, HttpServletResponse var2) throws AuthenticationException, IOException, ServletException;
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
String password = this.obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
//注意这里 将构造的Authentication转交给了AuthenticationManager去处理
return this.getAuthenticationManager().authenticate(authRequest);
}
}
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
boolean debug = logger.isDebugEnabled();
Iterator var6 = this.getProviders().iterator();
//在这里循环遍历处理请求
while(var6.hasNext()) {
AuthenticationProvider provider = (AuthenticationProvider)var6.next();
if (provider.supports(toTest)) {
if (debug) {
logger.debug("Authentication attempt using " + provider.getClass().getName());
}
try {
result = provider.authenticate(authentication);
if (result != null) {
this.copyDetails(authentication, result);
break;
}
} catch (AccountStatusException var11) {
this.prepareException(var11, authentication);
throw var11;
} catch (InternalAuthenticationServiceException var12) {
this.prepareException(var12, authentication);
throw var12;
} catch (AuthenticationException var13) {
lastException = var13;
}
}
}
if (result == null && this.parent != null) {
try {
result = this.parent.authenticate(authentication);
} catch (ProviderNotFoundException var9) {
;
} catch (AuthenticationException var10) {
lastException = var10;
}
}
if (result != null) {
if (this.eraseCredentialsAfterAuthentication && result instanceof CredentialsContainer) {
((CredentialsContainer)result).eraseCredentials();
}
this.eventPublisher.publishAuthenticationSuccess(result);
return result;
} else {
if (lastException == null) {
lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound", new Object[]{toTest.getName()}, "No AuthenticationProvider found for {0}"));
}
this.prepareException((AuthenticationException)lastException, authentication);
throw lastException;
}
}
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
}
//看这里
SecurityContextHolder.getContext().setAuthentication(authResult);
this.rememberMeServices.loginSuccess(request, response, authResult);
if (this.eventPublisher != null) {
this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
this.successHandler.onAuthenticationSuccess(request, response, authResult);
}
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
public interface UserDetails extends Serializable {
Collection extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
public interface Authentication extends Principal, Serializable {
Collection extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
public interface AuthenticationProvider {
Authentication authenticate(Authentication var1) throws AuthenticationException;
boolean supports(Class> var1);
}
public class User {
//账号的几种状态
public static String STATE_ACCOUNTEXPIRED = "ACCOUNTEXPIRED"; //是否过期
public static String STATE_LOCK = "LOCK"; //是否被锁定
public static String STATE_TOKENEXPIRED = "TOKENEXPIRED"; //TOKEN是否过期
public static String STATE_NORMAL = "NORMAL"; //是否可用
private String userid;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
private String username;
private String password;
private String state;
private String name;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
*
* 定义自己的UserDetails
*
*
*/
public class MyUserDetails implements UserDetails {
private User user;
private Collection extends GrantedAuthority> authorities;
public MyUserDetails(User user, Collection extends GrantedAuthority> authorities) {
super();
this.user = user;
this.authorities = authorities;
}
//序列化
private static final long serialVersionUID = 1L;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return this.user.getPassword();
}
@Override
public String getUsername() {
return this.user.getUsername();
}
//是否过期
@Override
public boolean isAccountNonExpired() {
return this.user.getState().equals(User.STATE_ACCOUNTEXPIRED);
}
//是否锁定
@Override
public boolean isAccountNonLocked() {
return this.user.getState().equals(User.STATE_LOCK);
}
//凭证是否过期
@Override
public boolean isCredentialsNonExpired() {
return this.user.getState().equals(User.STATE_TOKENEXPIRED);
}
//是否禁用
@Override
public boolean isEnabled() {
return this.user.getState().equals(User.STATE_NORMAL);
}
}
@Service("userDetailsService")
public class AuthUserDetailService implements UserDetailsService {
@Autowired
private UserInfoDao userInfoDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = null;
try{
User user = userInfoDao.getUserinfo(username);
if(user!=null){
String rolename = userInfoDao.getRoleByUserid(user.getUserid());
Collection authorities = new ArrayList<>();
SimpleGrantedAuthority grant = new SimpleGrantedAuthority(rolename);
authorities.add(grant);
//封装自定义的UserDetails
userDetails = new MyUserDetails(user, authorities);
}else{
throw new UsernameNotFoundException("该用户不存在!");
}
} catch (Exception e){
e.printStackTrace();
}
return userDetails;
}
}
@Component
public class UserInfoDao {
@Autowired
public JdbcTemplate jdbcTemplate;
public User getUserinfo(String username){
String sql = "select * from myuser where username = '"+username+"'";
System.out.println(sql);
List list = (List) jdbcTemplate.query(sql, new Object[] {},
new ResultSetExtractor() {
public Object extractData(ResultSet rs)
throws SQLException, DataAccessException {
List userinfo = new ArrayList();
while (rs.next()) {
userinfo.add(rs.getString(1));
userinfo.add(rs.getString(2));
userinfo.add(rs.getString(3));
userinfo.add(rs.getString(4));
userinfo.add(rs.getString(5));
}
return userinfo;
}
});
System.out.println(list.size());
User user = new User();
if(list.size()>0){
user.setUserid(list.get(0));
user.setUsername(list.get(1));
user.setPassword(list.get(2));
user.setState(list.get(3));
user.setName(list.get(4));
}
return user;
}
public String getRoleByUserid(String userid){
String roleid = "";
String rolename = "";
String sql = "select roleid from UserRole where userid = '"+userid+"'";
roleid = (String) jdbcTemplate.query(sql, new Object[] {},
new ResultSetExtractor() {
public Object extractData(ResultSet rs)
throws SQLException, DataAccessException {
String roleid = "";
while (rs.next()) {
roleid = rs.getString(1);
}
return roleid;
}
});
String sql2 = "select name from Role where id = ? ";
if(roleid!=null){
rolename = (String) jdbcTemplate.query(sql2, new Object[] {roleid},
new ResultSetExtractor() {
public Object extractData(ResultSet rs)
throws SQLException, DataAccessException {
String roleid = "";
while (rs.next()) {
roleid = rs.getString(1);
}
return roleid;
}
});
}
System.out.println("ROLENAME="+rolename);
return rolename;
}
}
CREATE TABLE `myuser` (
`id` int(11) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`state` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `role` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `userrole` (
`id` int(11) NOT NULL,
`userid` int(11) DEFAULT NULL,
`roleid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/**
*
* 自定义认证服务
*
*/
@Service("securityProvider")
public class SecurityProvider implements AuthenticationProvider {
private AuthUserDetailService userDetailsService;
public SecurityProvider(UserDetailsService userDetailsService) {
this.userDetailsService = (AuthUserDetailService) userDetailsService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken token
= (UsernamePasswordAuthenticationToken) authentication;
String username = token.getName();
System.out.println(username);
UserDetails userDetails = null;
if(username !=null) {
userDetails = userDetailsService.loadUserByUsername(username);
}
System.out.println("$$$"+userDetails);
// if(userDetails == null) {
// throw new UsernameNotFoundException("用户名/密码无效");
// } else if (!userDetails.isEnabled()){
// System.out.println("jinyong用户已被禁用");
// throw new DisabledException("用户已被禁用");
// }else if (!userDetails.isAccountNonExpired()) {
// System.out.println("guoqi账号已过期");
// throw new LockedException("账号已过期");
// }else if (!userDetails.isAccountNonLocked()) {
// System.out.println("suoding账号已被锁定");
// throw new LockedException("账号已被锁定");
// }else if (!userDetails.isCredentialsNonExpired()) {
// System.out.println("pingzheng凭证已过期");
// throw new LockedException("凭证已过期");
// }
System.out.println(token.getCredentials());
String password = userDetails.getPassword();
System.out.println(password);
System.out.println(userDetails.getAuthorities());
//与authentication里面的credentials相比较
if(!password.equals(token.getCredentials())) {
throw new BadCredentialsException("Invalid username/password");
}
//授权 一个userdetails表示一个principal
return new UsernamePasswordAuthenticationToken(userDetails, password,userDetails.getAuthorities());
}
@Override
public boolean supports(Class> authentication) {
//返回true后才会执行上面的authenticate方法,这步能确保authentication能正确转换类型
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
}
/**
* 继承WebSecurityConfigurerAdapter
* 添加自定义授权
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProvider securityProvider;
//认证管理器
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//自定义AuthenticationProvider
auth.authenticationProvider(securityProvider);
}
//自定义用户权限
//对http的操作就是在添加url-filter的关系映射
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user").hasRole("USER")
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/login").permitAll()
.and()
.formLogin()
.loginPage("/login") //跳转登录页面的控制器,该地址要保证和表单提交的地址一致!
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2)
throws IOException, ServletException {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null && principal instanceof UserDetails) {
UserDetails user = (UserDetails) principal;
System.out.println("loginUser:"+user.getUsername());
//维护在session中
arg0.getSession().setAttribute("userDetail", user);
arg1.sendRedirect("/");
}
}
})
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/index")
.permitAll()
.and()
.csrf() //关闭csrf 否则会出现跨域问题
.disable();
}
}