新建项目
添加json、aop、shiro的相关依赖
<dependency> <groupId>com.alibabagroupId> <artifactId>fastjsonartifactId> <version>1.2.54version> dependency>
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-aopartifactId> dependency> <dependency> <groupId>org.apache.shirogroupId> <artifactId>shiro-coreartifactId> <version>1.4.0version> dependency> <dependency> <groupId>org.apache.shirogroupId> <artifactId>shiro-springartifactId> <version>1.4.0version> dependency> <dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <optional>trueoptional> dependency> |
添加application配置
spring.datasource.url=jdbc:mysql://localhost:3306/xiangmu spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
mybatis.typeAliasesPackage=com.zjz.entity mybatis.mapperLocations=classpath:mapper/*.xml
|
shiro的配置
package com.zjz.config;
import java.util.LinkedHashMap; import java.util.Properties;
import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
@Configuration public class ShiroConfig {
/** * 解决setUnauthorizedUrl不能跳转的问题 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; }
/** * shiro的过滤器ShiroFilterFactoryBean, */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// Shiro的核心安全接口 shiroFilterFactoryBean.setSecurityManager(securityManager);
//没有登录发送请求时设置跳转到登录 shiroFilterFactoryBean.setLoginUrl("/test");
//访问没有权限的接口跳转的接口 //shiroFilterFactoryBean.setUnauthorizedUrl("/notPer");
//自定义过滤链,使用LinkedHashMap保证有序 LinkedHashMap
/* * 配置拦截规则,anon 表示资源都可以匿名访问 * authc:登录后能访问 */ filterChainDefinitionMap.put("/public/**", "anon"); //其他资源都需要认证 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/** * Shiro的核心安全接口 */ @Bean public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(customRealm());
return securityManager;
}
/** * 自定义realm */ @Bean public CustomRealm customRealm() {
return new CustomRealm(); }
@Bean public SimpleMappingExceptionResolver simpleMappingExceptionResolver() { SimpleMappingExceptionResolver simpleMappingExceptionResolver=new SimpleMappingExceptionResolver(); Properties properties=new Properties(); properties.setProperty("org.apache.shiro.authz.UnauthorizedException","/index/unauthorized"); properties.setProperty("org.apache.shiro.authz.UnauthenticatedException","/index/unauthorized"); simpleMappingExceptionResolver.setExceptionMappings(properties); return simpleMappingExceptionResolver; }
@Bean public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator; }
@Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } }
|
package com.zjz.config;
import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired;
import com.zjz.entity.Users; import com.zjz.service.UsersService;
public class CustomRealm extends AuthorizingRealm {
@Autowired private UsersService userInfoService; ;
/** * 授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("执行了授权"); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); return simpleAuthorizationInfo; }
/** * 认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了认证");
String loginname = (String) authenticationToken.getPrincipal();
Users user = userInfoService.getByUserName(loginname);
if (user == null) {
return null; } else { SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName()); System.out.println("users!=null" + simpleAuthenticationInfo); return simpleAuthenticationInfo; } } } |
package com.zjz.config;
import java.io.IOException;
import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component;
@Component @Configuration public class CORSFilter implements Filter {
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; HttpServletRequest request = (HttpServletRequest) servletRequest; // 允许哪些Origin发起跨域请求 String orgin = request.getHeader("Origin"); // response.setHeader( "Access-Control-Allow-Origin", config.getInitParameter( "AccessControlAllowOrigin" ) ); response.setHeader( "Access-Control-Allow-Origin", orgin ); // 允许请求的方法 response.setHeader( "Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PUT" ); //多少秒内,不需要再发送预检验请求,可以缓存该结果 response.setHeader( "Access-Control-Max-Age", "3600" ); // 表明它允许跨域请求包含xxx头 response.setHeader( "Access-Control-Allow-Headers", "x-auth-token,Origin,Access-Token,X-Requested-With,Content-Type, Accept" ); //是否允许浏览器携带用户身份信息(cookie) response.setHeader( "Access-Control-Allow-Credentials", "true" ); //prefight请求 if (request.getMethod().equals( "OPTIONS" )) { response.setStatus( 200 ); return; } chain.doFilter( servletRequest, response ); }
} |
package com.zjz.util;
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random;
import org.apache.shiro.codec.Hex;
public class MD5Util {
/** * 普通MD5加密 * * @param input * @return */ public static String MD5(String input) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { return "check jdk"; } catch (Exception e) { e.printStackTrace(); return ""; } char[] charArray = input.toCharArray(); byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString();
}
/** * 加盐MD5加密 * * @param password * @return */ public static String getMD5(String password) { Random r = new Random(); StringBuilder sb = new StringBuilder(16); sb.append(r.nextInt(99999999)).append(r.nextInt(99999999)); int len = sb.length(); if (len < 16) { for (int i = 0; i < 16 - len; i++) { sb.append("0"); } } String salt = sb.toString(); password = md5Hex(password + salt); char[] cs = new char[48]; for (int i = 0; i < 48; i += 3) { cs[i] = password.charAt(i / 3 * 2); char c = salt.charAt(i / 3); cs[i + 1] = c; cs[i + 2] = password.charAt(i / 3 * 2 + 1); } return new String(cs); }
/** * 校验加盐后是否和原文一致 * * @param password * @param md5 * @return */ public static boolean verify(String password, String md5) { try { char[] cs1 = new char[32]; char[] cs2 = new char[16]; for (int i = 0; i < 48; i += 3) { cs1[i / 3 * 2] = md5.charAt(i); cs1[i / 3 * 2 + 1] = md5.charAt(i + 2); cs2[i / 3] = md5.charAt(i + 1); } String salt = new String(cs2); return md5Hex(password + salt).equals(new String(cs1)); } catch (Exception e) { return false; }
}
/** * 获取十六进制字符串形式的MD5摘要 */ private static String md5Hex(String src) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bs = md5.digest(src.getBytes()); return new String(new Hex().encode(bs)); } catch (Exception e) { return null; } }
} |
4写控制器
使用hbuilder新建web项目
提供一个js文件
|
6页面js、html
登录页面
登录成功