1.首先编写xml配置文件
<!-- 定义用户自定义的realm-->
<bean id="myrealm" class="com.hfxt.controller.shiro.UserRealm">
<!-- 设置加密匹配器-->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashIterations" value="1024"></property>
<property name="hashAlgorithmName" value="md5"></property>
</bean>
</property>
</bean>
<!-- 引用了工具类-->
<bean id="roleOrFillter" class="com.hfxt.controller.shiro.CustomRolesAuthorizationFilter"/>
<!-- 配置权限管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms" >
<list>
<ref bean="myrealm"/>
</list>
</property>
</bean>
<!-- logout过滤器-->
<bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/loginAjax.jsp" />
</bean>
<!-- 配置过滤器工厂-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用配置好的过滤管理器-->
<property name="securityManager" ref="securityManager"/>
<!-- 登录页面-->
<property name="loginUrl" value="/login/tologin.html"/>
<!-- 登陆成功页面-->
<property name="successUrl" value="/filmInfo/index.html"/>
<!-- 权限不足页面-->
<property name="unauthorizedUrl" value="/login/unauthorized"/>
<!-- 引用工具类实现满足一个角色权限即可["buyer,operator"]-->
<property name="filters" >
<map>
<entry key="roleOrFilter" value-ref="roleOrFillter"/>
</map>
</property>
<!-- 权限配置-->
<property name="filterChainDefinitions">
<!-- anno可以匿名访问,即可以不用登录就可以访问;-->
<!-- authc必须登录之后才可以访问;-->
<!-- logout 退出 由于shiro有缓存机制 必须登出-->
<value>
/login/**=anon
/filmInfo/**=authc,roles["buyer,operator"] /filmInfo/**=authc,roleOrFilter["buyer,operator"]
/shop/**=authc
/echar.jsp=authc
/logout.jsp = logout
</value>
</property>
</bean>
2.实现shiro角色 引用工具类实现满足一个角色权限即可[“buyer,operator”]的工具类
package com.hfxt.controller.shiro;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class CustomRolesAuthorizationFilter extends AuthorizationFilter {
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue;
//没有角色限制,有权限访问
if (rolesArray == null || rolesArray.length == 0) {
return true;
}
for (int i = 0; i < rolesArray.length; i++) {
//若当前用户是rolesArray中的任何一个,则有权限访问
if (subject.hasRole(rolesArray[i])) {
return true;
}
}
return false;
}
}
3.对UsernamePasswordToken类进行封装的工具类
package com.hfxt.controller.shiro;
import org.apache.shiro.authc.UsernamePasswordToken;
public class CustomToken extends UsernamePasswordToken {
public CustomToken() {
super();
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted during an authentication attempt, with a <tt>null</tt>
* {@link #getHost() host} and a <tt>rememberMe</tt> default of <tt>false</tt>.
*
* @param username
* the username submitted for authentication
* @param password
* the password character array submitted for authentication
*/
public CustomToken(final String username, final char[] password) {
this(username, password, false, null);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted during an authentication attempt, with a <tt>null</tt>
* {@link #getHost() host} and a <tt>rememberMe</tt> default of <tt>false</tt>
* <p/>
* <p>
* This is a convience constructor and maintains the password internally via a character array, i.e. <tt>password.toCharArray();</tt>. Note that storing a
* password as a String in your code could have possible security implications as noted in the class JavaDoc.
* </p>
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
*/
public CustomToken(final String username, final String password) {
this(username, password != null ? password.toCharArray() : null, false, null);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the inetAddress from where the attempt is occurring, and a
* default <tt>rememberMe</tt> value of <tt>false</tt>
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
* @param host
* the host name or IP string from where the attempt is occuring
* @since 0.2
*/
public CustomToken(final String username, final char[] password, final String host) {
this(username, password, false, host);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the inetAddress from where the attempt is occurring, and a
* default <tt>rememberMe</tt> value of <tt>false</tt>
* <p/>
* <p>
* This is a convience constructor and maintains the password internally via a character array, i.e. <tt>password.toCharArray();</tt>. Note that storing a
* password as a String in your code could have possible security implications as noted in the class JavaDoc.
* </p>
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
* @param host
* the host name or IP string from where the attempt is occuring
* @since 1.0
*/
public CustomToken(final String username, final String password, final String host) {
this(username, password != null ? password.toCharArray() : null, false, host);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user wishes their identity to be remembered
* across sessions.
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
* @param rememberMe
* if the user wishes their identity to be remembered across sessions
* @since 0.9
*/
public CustomToken(final String username, final char[] password, final boolean rememberMe) {
this(username, password, rememberMe, null);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user wishes their identity to be remembered across
* sessions, and the inetAddress from where the attempt is ocurring.
* <p/>
* <p>
* This is a convience constructor and maintains the password internally via a character array, i.e. <tt>password.toCharArray();</tt>. Note that storing a
* password as a String in your code could have possible security implications as noted in the class JavaDoc.
* </p>
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
* @param rememberMe
* if the user wishes their identity to be remembered across sessions
* @param host
* the host name or IP string from where the attempt is occuring
* @since 1.0
*/
public CustomToken(final String username, final String password, final boolean rememberMe, final String host) {
this(username, password != null ? password.toCharArray() : null, rememberMe, host);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user wishes their identity to be remembered
* across sessions.
* <p/>
* <p>
* This is a convience constructor and maintains the password internally via a character array, i.e. <tt>password.toCharArray();</tt>. Note that storing a
* password as a String in your code could have possible security implications as noted in the class JavaDoc.
* </p>
*
* @param username
* the username submitted for authentication
* @param password
* the password string submitted for authentication
* @param rememberMe
* if the user wishes their identity to be remembered across sessions
* @since 0.9
*/
public CustomToken(final String username, final String password, final boolean rememberMe) {
this(username, password != null ? password.toCharArray() : null, rememberMe, null);
}
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user wishes their identity to be remembered across
* sessions, and the inetAddress from where the attempt is ocurring.
*
* @param username
* the username submitted for authentication
* @param password
* the password character array submitted for authentication
* @param rememberMe
* if the user wishes their identity to be remembered across sessions
* @param host
* the host name or IP string from where the attempt is occuring
* @since 1.0
*/
public CustomToken(final String username, final char[] password, final boolean rememberMe, final String host) {
super(username, password, rememberMe, host);
/**
* 增加手机登录验证token.
*/
}
private String mobile;
private String verificatecode;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getVerificatecode() {
return verificatecode;
}
public void setVerificatecode(String verificatecode) {
this.verificatecode = verificatecode;
}
public CustomToken(final String username, final String password,final String mobile ,final String verificatecode, final String host) {
this(username, password != null ? password.toCharArray() : null, false, host);
this.mobile = mobile;
this.verificatecode = verificatecode;
}
/**
*/
public static final int Flag_Front_User = 1;
/**
*/
public static final int Flag_Admin_User = 2;
/**
*/
private int flagFrontOrAdmin = 0;
/**
*/
public int getFlagFrontOrAdmin() {
return flagFrontOrAdmin;
}
/**
*/
public void setFlagFrontOrAdmin(int flagFrontOrAdmin) {
this.flagFrontOrAdmin = flagFrontOrAdmin;
}
}
4.controller 层处理的代码
package com.hfxt.controller;
import com.alibaba.fastjson.JSONArray;
import com.hfxt.controller.shiro.CustomToken;
import com.hfxt.entity.UserVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping("tologin.html")
public String tologin()
{
return "loginAjax";
}
@RequestMapping("login.html")
@ResponseBody
public String login(UserVo uservo)
{
Map<String,Object> maps=new HashMap<String, Object>();
//创建shiro认证对象
try{
Subject subject= SecurityUtils.getSubject();
// 封装认证用户 继承usernamepasswordtocken
// UsernamePasswordToken token=new UsernamePasswordToken()
CustomToken token=new CustomToken(uservo.getUsername(),uservo.getPassword());
//提交认证
subject.login(token);
maps.put("retcode",1);
maps.put("retmsg","登录成功");
}
catch(UnknownAccountException e){
maps.put("retcode",-1);
maps.put("retmsg","账户不正确");
}catch (IncorrectCredentialsException e)
{
maps.put("retcode",-1);
maps.put("retmsg","密码不正确");
}
catch (AuthenticationException e)
{
maps.put("retcode",-1);
maps.put("retmsg","认证失败,请联系管理员");
}
return JSONArray.toJSONString(maps);
}
@RequestMapping("unauthorized")
public String fail()
{
return "403";
}
}
6.授权加认证
package com.hfxt.controller.shiro;
import com.hfxt.entity.RoleVo;
import com.hfxt.entity.UserVo;
import com.hfxt.service.RoleVoService;
import com.hfxt.service.UserVoService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.List;
public class UserRealm extends AuthorizingRealm {
@Resource
protected UserVoService userVoService;
@Resource
protected RoleVoService roleVoService;
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 声明返回授权对象
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
UserVo userVo= (UserVo) SecurityUtils.getSubject().getPrincipal();
//获取角色
List<RoleVo> list=roleVoService.getRoleVosByUserid(userVo.getId().intValue());
for(RoleVo roleVo :list)
{
info.addRole(roleVo.getRoleCode());
}
return info;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws
AuthenticationException {
//得到认证对象
String username= (String) token.getPrincipal();
String password=new String( (char []) token.getCredentials());
UserVo userVo=null;
try{
userVo=userVoService.getUserVoByUserVoName(username);
}
catch(Exception e){
e.printStackTrace();
}
if (userVo == null) {
throw new UnknownAccountException();
}
//加密算法
String newpwd=new Md5Hash(password,userVo.getSalt(),1024).toString();
System.out.println("加密之后:"+newpwd);
System.out.println("数据库的密码:"+ userVo.getPassword());
if(!userVo.getPassword().equals(newpwd))
{
throw new IncorrectCredentialsException();
}
//进行认证
//第一个参数 user
//第二个参数是user.getpassword;
//第三个参数(密码加密 salt(盐值)) 可省
//第四个参数是当前realm的名字
ByteSource sale=ByteSource.Util.bytes(userVo.getSalt());
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(userVo, userVo.getPassword(),sale,getName());
return info;
}
}
web.xml配置监听器监听
<!-- 配置shiro拦截器(权限验证)-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>