There is no difference if you do not put $* or $@ in quotes. But if you put them inside quotes (which you should, as a general good practice), then $@ will pass your parameters as separate parameters, whereas $* will just pass all params as a single parameter.
Take these scripts (foo.sh and bar.sh) for testing:
>> cat bar.sh
echo "Arg 1: $1"
echo "Arg 2: $2"
echo "Arg 3: $3"
echo
>> cat foo.sh
echo '$* without quotes:'
./bar.sh $*
echo '$@ without quotes:'
./bar.sh $@
echo '$* with quotes:'
./bar.sh "$*"
echo '$@ with quotes:'
./bar.sh "$@"
Now this example should make everything clear:
>> ./foo.sh arg1 "arg21 arg22" arg3
$* without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$@ without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$* with quotes:
Arg 1: arg1 arg21 arg22 arg3
Arg 2:
Arg 3:
$@ with quotes:
Arg 1: arg1
Arg 2: arg21 arg22
Arg 3: arg3
Clearly, "$@" gives the behaviour that we generally want.
More detailed description:
Case 1: No quotes around $* and $@:
Both have same behaviour.
./bar.sh $* => bar.sh gets arg1, arg2 and arg3 as separate arguments
./bar.sh $@ => bar.sh gets arg1, arg2 and arg3 as separate arguments
Case 2: You use quotes around $* and $@:
./bar.sh "$*" => bar.sh gets arg1 arg2 arg3 as a single argument
./bar.sh "$@" => bar.sh gets arg1, arg2 and arg3 as a separate arguments
More importantly, $* also ignores quotes in your argument list. For example, if you had supplied ./foo.sh arg1 "arg2 arg3", even then:
./bar.sh "$*" => bar.sh will still receive arg2 and arg3 as separate parameters!
./bar.sh "$@" => will pass arg2 arg3 as a single parameter (which is what you usually want).
Notice again that this difference occurs only if you put $* and $@ in quotes. Otherwise they have the same behaviour.
Official documentation: http://www.gnu.org/software/bash/manual/bash.html#Special-Parameters