导入相关pom
<properties>
<shiro-version>1.3.2</shiro-version>
</properties>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.4</version>
</dependency>
首先需要创建自定义realm继承AuthorizingRealm,然后编写相关代码,这里要注册bean,所以spring需要扫描进去
@Component
public class myRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("正在进行授权认证");
String username = (String) principals.getPrimaryPrincipal();
Set<String> strings = userService.listPermissionsByUserName(new User(username));
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.setStringPermissions(strings);
System.out.println("授权成功");
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("正在进行登陆认证");
UsernamePasswordToken token1= (UsernamePasswordToken) token;
User user = userService.loadByUsername(new User(token1.getUsername()));
if(null==user){
throw new UnknownAccountException();
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(),
user.getPassword(),
ByteSource.Util.bytes(user.getSalt()),
getName()
);
return authenticationInfo;
}
编写spring-shiro.xml文件并导入spring.xml中 ,这里密码使用的是MD5加密验证,利用shiro加密工具类进行加密
package com.shiro;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
/**
* 用于shiro权限认证的密码工具类
*/
public class PasswordHelper {
/**
* 随机数生成器
*/
private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
/**
* 指定hash算法为MD5
*/
private static final String hashAlgorithmName = "md5";
/**
* 指定散列次数为1024次,即加密1024次
*/
private static final int hashIterations = 1024;
/**
* true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储
*/
private static final boolean storedCredentialsHexEncoded = true;
/**
* 获得加密用的盐
*
* @return
*/
public static String createSalt() {
return randomNumberGenerator.nextBytes().toHex();
}
/**
* 获得加密后的凭证
*
* @param credentials 凭证(即密码)
* @param salt 盐
* @return
*/
public static String createCredentials(String credentials, String salt) {
SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,
salt, hashIterations);
return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();
}
/**
* 进行密码验证
*
* @param credentials 未加密的密码
* @param salt 盐
* @param encryptCredentials 加密后的密码
* @return
*/
public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {
return encryptCredentials.equals(createCredentials(credentials, salt));
}
public static void main(String[] args) {
String salt = createSalt();
System.out.println(salt);
System.out.println(salt.length());
String credentials = createCredentials("888888", salt);
System.out.println(credentials);
System.out.println(credentials.length());
}
}
这里配置我们登陆时将密码转化成MD5进行比较
<bean class="com.shiro.myRealm" id="myRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1024"></property>
<property name="storedCredentialsHexEncoded" value="true"></property>
</bean>
</property>
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"></property>
</bean>
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<!-- 访问页面之前未经认证,必定跳转到登陆页面 -->
<property name="loginUrl" value="/login.jsp"/>
<property name="unauthorizedUrl" value="/unknown.jsp"></property>
<!-- 配置认证页面 -->
<!-- anon表示匿名访问 -->
<!-- authc表示进过认证方能访问 -->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/authentication/** = authc
</value>
</property>
</bean>
这个时候就可以进行相关登陆操作
@RequestMapping("/login")
public String login(@RequestParam("username") String name, @RequestParam("password") String pass,Map<String,Object> map){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(name, pass);
try {
subject.login(token);
System.out.println("用户是否登录成功:" + subject.isAuthenticated());
} catch (AuthenticationException e) {
e.printStackTrace();
map.put("msg", "登陆失败");
return "failure";
}
map.put("msg", "登陆成功");
return "/authentication/list";
}
如果需要用到权限模块,继承自定义realm实现了AuthorizingRealm的doGetAuthorizationInfo方法,并编写相关代码
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("正在进行授权认证");
String username = (String) principals.getPrimaryPrincipal();
Set<String> strings = userService.listPermissionsByUserName(new User(username));
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.setStringPermissions(strings);
System.out.println("授权成功");
return info;
}
这个方法在shiro进行权限认证的时候会进行调用比如使用shiro标签认证,注解认证,subject.isPermitted()
这里会有一个问题,注解认证无法使用,我们需要在spring-mvc.xml里面加入shiro注解
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
这里我们的shirofileter里面配置的unauthorizedUrl(未授权所跳转的url)就会失效,我们需要在spring-mvc.xml里面再加入
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">unknown</prop>
<!--
<prop key="org.apache.shiro.authz.UnauthenticatedException">jsp/unauthorized</prop>
-->
<!--
<prop key="org.apache.shiro.authz.AuthorizationException">jsp/unauthorized</prop>
-->
<!--
<prop key="java.lang.Throwable">jsp/unauthorized</prop>
-->
</props>
</property>
</bean>