在上一篇Day 25 - Spring Security (二) UserDetailsService中有实作了UserDetailsService 进行基本的使用者资讯验证,而实务上我们不会只简单比对使用者名称和密码,还会检查帐号状态等资讯,因此我们这篇文章来实作自定义的AuthenticationProvider。
package com.example.iThomeIronMan.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.example.iThomeIronMan.security.CustomAuthenticationFailureHandler;
import com.example.iThomeIronMan.security.CustomAuthenticationProvider;
import com.example.iThomeIronMan.security.CustomAuthenticationSuccessHandler;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider authProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
auth.authenticationProvider(authProvider);
}
// 忽略...
}
package com.example.iThomeIronMan.service.impl;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.iThomeIronMan.dao.MemberAccountDao;
import com.example.iThomeIronMan.model.Member;
import com.example.iThomeIronMan.model.MemberAccount;
import com.example.iThomeIronMan.service.MemberAccountService;
import com.example.iThomeIronMan.service.MemberService;
import com.example.iThomeIronMan.service.ex.AccountDuplicateException;
import com.example.iThomeIronMan.service.ex.InsertException;
@Service
public class MemberAccountServiceImpl implements MemberAccountService, UserDetailsService {
// 忽略...
public MemberAccount login(MemberAccount memberAccount) {
// 检查帐号是否存在
MemberAccount data = memberAccountDao.getMemberAccountByAccount(memberAccount.getAccount());
if(data == null) {
return null;
}
// 比对密码
if(!passwordEncoder.matches(memberAccount.getPassword() + data.getSalt(), data.getPassword())) return null;
return data;
}
}
package com.example.iThomeIronMan.security;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import com.example.iThomeIronMan.model.MemberAccount;
import com.example.iThomeIronMan.service.MemberAccountService;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private MemberAccountService memberAccountService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// TODO Auto-generated method stub
String account = authentication.getName();
String password = String.valueOf(authentication.getCredentials());
try {
MemberAccount memberAccount = new MemberAccount();
memberAccount.setAccount(account);
memberAccount.setPassword(password);
memberAccount = memberAccountService.login(memberAccount);
Collection<? extends GrantedAuthority> authorities = memberAccount.getAuthorities();
return new UsernamePasswordAuthenticationToken(memberAccount, password, authorities);
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
<<: EP 26 - [Ruby on Rails] 使用状态机管理订单
前言 专案管理是一门很深的学问,也不只是软件业,各行各业都有,最早是来自土木建筑、国防领域。 牵扯到...
CAN Protocol 介绍 CAN 全名为控制器区域网路 (Controller Area Ne...
延续昨天的构想,今天来试试看能否成功。 昨天的构想好像有点错误,因为购物车只会有1台,且纪录是暂时的...
有点惨,上篇说得想办法把FPU塞进来的路给打通,但是实在受限硬体资源,有点悲剧。 我是已经订了一张8...
在 Livewire 上的操作都会透过 AJAX 将资料往返与前後端之间,有些较长的请求可能不会即时...