Vue+Jwt+SpringBoot+Ldap完成登录认证的示例代码(3)
2.2应用配置文件
#Logging_config logging.level.root=INFO logging.level.org.springframework.web=WARN logging.file=minibox.log #server_config #使用了SSL,并且在ldap配置中使用了ldaps,这里同时也需要把AD的证书导入到server.keystore中。具体的可以查看java的keytool工具 server.port=8443 server.ssl.key-store=classpath:server.keystore server.ssl.key-store-password=minibox server.ssl.key-password=minibox #jwt #jwt加解密时使用的key jwt.key=minibox #ldap_config #ldap配置信息,注意这里的userDn一定要写这种形式。referral设置为follow,说不清用途,似乎只有连接AD时才需要配置 ldap.url=ldaps://192.168.227.128:636 ldap.base=ou=Employees,dc=minibox,dc=com ldap.userDn=cn=Administrator,cn=Users,dc=minibox,dc=com ldap.userPwd=qqq111!!!! ldap.referral=follow ldap.domainName=@minibox.com
3.Spring主配置类
package an; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.support.LdapContextSource; @SpringBootApplication//相当于@Configuration,@EnableAutoConfiguration,@ComponentScan public class Application { /* * SpringLdap配置。通过@Value注解读取之前配置文件中的值 */ @Value("${ldap.url}") private String ldapUrl; @Value("${ldap.base}") private String ldapBase; @Value("${ldap.userDn}") private String ldapUserDn; @Value("${ldap.userPwd}") private String ldapUserPwd; @Value("${ldap.referral}") private String ldapReferral; /* *SpringLdap的javaConfig注入方式 */ @Bean public LdapTemplate ldapTemplate() { return new LdapTemplate(contextSourceTarget()); } @Bean public LdapContextSource contextSourceTarget() { LdapContextSource ldapContextSource = new LdapContextSource(); ldapContextSource.setUrl(ldapUrl); ldapContextSource.setBase(ldapBase); ldapContextSource.setUserDn(ldapUserDn); ldapContextSource.setPassword(ldapUserPwd); ldapContextSource.setReferral(ldapReferral); return ldapContextSource; } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
3.1提供认证服务的类
package an.auth; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.ldap.NamingException; import org.springframework.ldap.core.AttributesMapper; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.support.LdapUtils; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import static org.springframework.ldap.query.LdapQueryBuilder.query; import java.util.Date; import java.util.HashMap; import java.util.Map; import an.entity.Employee; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @RestController @RequestMapping("/auth") public class JwtAuth { //jwt加密密匙 @Value("${jwt.key}") private String jwtKey; //域名后缀 @Value("${ldap.domainName}") private String ldapDomainName; //ldap模板 @Autowired private LdapTemplate ldapTemplate; /** * 将域用户属性通过EmployeeAttributesMapper填充到Employee类中,返回一个填充信息的Employee实例 */ private class EmployeeAttributesMapper implements AttributesMapper<Employee> { public Employee mapFromAttributes(Attributes attrs) throws NamingException, javax.naming.NamingException { Employee employee = new Employee(); employee.setName((String) attrs.get("sAMAccountName").get()); employee.setDisplayName((String) attrs.get("displayName").get()); employee.setRole((String) attrs.get("memberOf").toString()); return employee; } } /** * @param username 用户提交的名称 * @param password 用户提交的密码 * @return 成功返回加密后的token信息,失败返回错误HTTP状态码 */ @CrossOrigin//因为需要跨域访问,所以要加这个注解 @RequestMapping(method = RequestMethod.POST) public ResponseEntity<String> authByAd( @RequestParam(value = "username") String username, @RequestParam(value = "password") String password) { //这里注意用户名加域名后缀 userDn格式:anwx@minibox.com String userDn = username + ldapDomainName; //token过期时间 4小时 Date tokenExpired = new Date(new Date().getTime() + 60*60*4*1000); DirContext ctx = null; try { //使用用户名、密码验证域用户 ctx = ldapTemplate.getContextSource().getContext(userDn, password); //如果验证成功根据sAMAccountName属性查询用户名和用户所属的组 Employee employee = ldapTemplate .search(query().where("objectclass").is("person").and("sAMAccountName").is(username), new EmployeeAttributesMapper()) .get(0); //使用Jwt加密用户名和用户所属组信息 String compactJws = Jwts.builder() .setSubject(employee.getName()) .setAudience(employee.getRole()) .setExpiration(tokenExpired) .signWith(SignatureAlgorithm.HS512, jwtKey).compact(); //登录成功,返回客户端token信息。这里只加密了用户名和用户角色,而displayName和tokenExpired没有加密 Map<String, Object> userInfo = new HashMap<String, Object>(); userInfo.put("token", compactJws); userInfo.put("displayName", employee.getDisplayName()); userInfo.put("tokenExpired", tokenExpired.getTime()); return new ResponseEntity<String>(JSON.toJSONString(userInfo , SerializerFeature.DisableCircularReferenceDetect) , HttpStatus.OK); } catch (Exception e) { //登录失败,返回失败HTTP状态码 return new ResponseEntity<String>(HttpStatus.UNAUTHORIZED); } finally { //关闭ldap连接 LdapUtils.closeContext(ctx); } } }
内容版权声明:除非注明,否则皆为本站原创文章。