之前已经写了注解和xml配合搭建基本认证、页面认证、授权码认证、替换6位授权码方法等,这次在前面的基础上介绍如何替换用户名密码认证,下一篇介绍如何增加验证码等额外参数验证方法。
代码比较多,这次只贴出来部分,完整代码在
git地址:https://gitee.com/ffch/OauthUmp
spring Security4 和 oauth2整合 注解+xml混合使用(基础运行篇)
spring Security4 和 oauth2整合 注解+xml混合使用(进阶篇)
spring Security4 和 oauth2整合 注解+xml混合使用(授权码篇)
spring Security4 和 oauth2整合 注解+xml混合使用(注意事项篇)
spring Security4 和 oauth2整合 注解+xml混合使用(替换6位的授权码)
spring Security4 和 oauth2整合 注解+xml混合使用(替换用户名密码认证)
spring Security4 和 oauth2整合 注解+xml混合使用(验证码等额外数据验证)
首先,我们假设用户名密码是通过service层获取的。这个逻辑就可以按照自己的逻辑去写了。
1.实体
package com.ump.domain;
import java.util.UUID;
public class AppUser {
private String uuid;
private String userName;
private String password;
private String userType;
public AppUser() {
}
public AppUser(String userName, String password) {
this.userName = userName;
this.password = password;
this.uuid = UUID.randomUUID().toString();
this.userType = "1";
}
public AppUser(AppUser appUser) {
this.userName = appUser.userName;
this.password = appUser.password;
this.uuid = appUser.uuid;
this.userType = appUser.userType;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
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 getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
}
2.service服务
package com.ump.service;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.stereotype.Service;
import com.ump.domain.AppUser;
@Service
public class AppUserService {
public AppUser findByName(String userName) {
Map users = new HashMap();
AppUser user1 = new AppUser();
user1.setUserName("bill");
user1.setPassword("abc123");
user1.setUserType("1");
user1.setUuid(UUID.randomUUID().toString());
users.put("bill", user1);
AppUser user2 = new AppUser();
user2.setUserName("bob");
user2.setPassword("abc123");
user2.setUserType("1");
user2.setUuid(UUID.randomUUID().toString());
users.put("bob", user2);
return users.get(userName);
}
}
用户来源不是直接指定了,而是从service层取了,所以我们要自定义UserDetails
package com.ump.oauth.detail;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import com.ump.domain.AppUser;
public class OauthUserDetails extends AppUser implements UserDetails{
public OauthUserDetails(AppUser appUser) {
super(appUser);
}
/**
*
*/
private static final long serialVersionUID = 6272869114201567325L;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return AuthorityUtils.createAuthorityList("USER");
}
@Override
public String getUserType() {
return super.getUserType();
}
@Override
public String getUsername() {
return super.getUserName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
我们需要提供loadUserByUsername方法。
package com.ump.oauth.part;
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.stereotype.Service;
import com.ump.domain.AppUser;
import com.ump.oauth.detail.OauthUserDetails;
import com.ump.service.AppUserService;
@Service("oauthUserDetailsService")
public class OauthUserDetailsService implements UserDetailsService {
@Autowired
private AppUserService appUserService;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
AppUser user;
try {
user = appUserService.findByName(userName);
} catch (Exception e) {
throw new UsernameNotFoundException("user select fail");
}
if(user == null){
throw new UsernameNotFoundException("no user found");
} else {
try {
return new OauthUserDetails(user);
} catch (Exception e) {
throw new UsernameNotFoundException("user role select fail");
}
}
}
}
AuthenticationProvider提供认证逻辑。
package com.ump.oauth.part;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
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.ump.oauth.detail.OauthAddUserDetails;
import com.ump.oauth.detail.OauthUserDetails;
@Component
public class OauthAuthenticationProvider implements AuthenticationProvider {
@Autowired
private OauthUserDetailsService oauthUserDetailsService;
/**
* 自定义验证方式
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//验证码等校验
// OauthAddUserDetails details = (OauthAddUserDetails) authentication.getDetails();
//
// System.out.println(details.getToken() + "+++++++++++++++++" + details.getSessionToken());
// if (!details.getToken().equalsIgnoreCase(details.getSessionToken())) {
// throw new BadCredentialsException("验证码错误。");
// }
//用户名密码校验
OauthUserDetails oauthUserDetails = (OauthUserDetails) oauthUserDetailsService
.loadUserByUsername(authentication.getName());
System.out.println(authentication.getName() + "+++++++++++++++++" + authentication.getCredentials());
if (!oauthUserDetails.getUserName().equals(authentication.getName())
|| !oauthUserDetails.getPassword().equals(authentication.getCredentials())) {
throw new BadCredentialsException("用户名或密码错误。");
}
Collection extends GrantedAuthority> authorities = oauthUserDetails.getAuthorities();
return new UsernamePasswordAuthenticationToken(oauthUserDetails.getUsername(), oauthUserDetails.getPassword(),
authorities);
}
@Override
public boolean supports(Class> arg0) {
return true;
}
}
继承WebSecurityConfigurerAdapter的OAuth2SecurityConfiguration需要指向AuthenticationProvider。
package com.ump.oauth.config;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import com.ump.oauth.part.OauthAuthenticationProvider;
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("myClientDetailsService")
private ClientDetailsService clientDetailsService;
// @Autowired
// @Qualifier("myUserDetailsService")
// private UserDetailsService userDetailsService;
// @Autowired
// public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
// //auth.userDetailsService(userDetailsService);
// auth.inMemoryAuthentication()
// .withUser("bill").password("abc123").roles("ADMIN").and()
// .withUser("bob").password("abc123").roles("USER");
// }
@Autowired
private OauthAuthenticationProvider oauthAuthenticationProvider;
@Autowired
@Qualifier("oauthAuthenticationDetailsSource")
private AuthenticationDetailsSource authenticationDetailsSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(oauthAuthenticationProvider);
}
@Override
public void configure(HttpSecurity http) throws Exception {
SimpleUrlAuthenticationFailureHandler hander = new SimpleUrlAuthenticationFailureHandler();
hander.setUseForward(true);
hander.setDefaultFailureUrl("/authlogin.jsp");
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/token")
.permitAll().and()
.formLogin().loginPage("/authlogin.jsp")
.usernameParameter("userName").passwordParameter("userPwd")
.authenticationDetailsSource(authenticationDetailsSource)
// .loginProcessingUrl("/login").failureUrl("/index1.jsp")
.loginProcessingUrl("/login").failureHandler(hander)
.and().logout().logoutUrl("/logout");
http.authorizeRequests().antMatchers("/user/**").authenticated();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
这样就可以了,中间有其他代码,删减即可,增加验证码的逻辑单独分开了,方便扩展。下一篇说明。